From 415c34935c58c05b5ca0e99a10198f871a90edf4 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 16 Jun 2011 21:40:18 -0600 Subject: Implement Progress class. --- libdimension-python/Makefile.am | 4 ++- libdimension-python/dimension.pxd | 15 ++++++++++ libdimension-python/dimension.pyx | 58 +++++++++++++++++++++++++++++++++++---- libdimension-python/platform.c | 41 +++++++++++++++++++++++++++ libdimension-python/platform.h | 29 ++++++++++++++++++++ 5 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 libdimension-python/platform.c create mode 100644 libdimension-python/platform.h (limited to 'libdimension-python') diff --git a/libdimension-python/Makefile.am b/libdimension-python/Makefile.am index c1f5274..90d7d45 100644 --- a/libdimension-python/Makefile.am +++ b/libdimension-python/Makefile.am @@ -29,7 +29,9 @@ dimension.c: dimension.pyx dimension.pxd cython --line-directives dimension.pyx pyexec_LTLIBRARIES = dimension.la -dimension_la_SOURCES = dimension.c +dimension_la_SOURCES = dimension.c \ + platform.c \ + platform.h dimension_la_LDFLAGS = -avoid-version -module dimension_la_LIBADD = $(top_builddir)/libdimension/libdimension.la diff --git a/libdimension-python/dimension.pxd b/libdimension-python/dimension.pxd index b73b99c..6ac6319 100644 --- a/libdimension-python/dimension.pxd +++ b/libdimension-python/dimension.pxd @@ -64,6 +64,16 @@ cdef extern from "../libdimension/dimension.h": void dmnsn_array_remove(dmnsn_array *array, size_t i) void dmnsn_array_apply(dmnsn_array *array, dmnsn_callback_fn *callback) + ############ + # Progress # + ############ + + ctypedef struct dmnsn_progress + + int dmnsn_finish_progress(dmnsn_progress *progress) + double dmnsn_get_progress(dmnsn_progress *progress) + void dmnsn_wait_progress(dmnsn_progress *progress, double prog) + ########## # Timers # ########## @@ -178,6 +188,7 @@ cdef extern from "../libdimension/dimension.h": int dmnsn_png_optimize_canvas(dmnsn_canvas *canvas) int dmnsn_png_write_canvas(dmnsn_canvas *canvas, FILE *file) + dmnsn_progress *dmnsn_png_write_canvas_async(dmnsn_canvas *canvas, FILE *file) int dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas) int dmnsn_gl_write_canvas(dmnsn_canvas *canvas) @@ -377,3 +388,7 @@ cdef extern from "../libdimension/dimension.h": void dmnsn_delete_scene(dmnsn_scene *scene) void dmnsn_raytrace_scene(dmnsn_scene *scene) + dmnsn_progress *dmnsn_raytrace_scene_async(dmnsn_scene *scene) + +cdef extern from "platform.h": + unsigned int dmnsn_terminal_width() diff --git a/libdimension-python/dimension.pyx b/libdimension-python/dimension.pyx index d5fbd1f..e1aba28 100644 --- a/libdimension-python/dimension.pyx +++ b/libdimension-python/dimension.pyx @@ -28,11 +28,53 @@ import os # Globals # ########### -# Make warnings fatal def die_on_warnings(always_die): """Whether to treat Dimension warnings as errors.""" dmnsn_die_on_warnings(always_die) +def terminal_width(): + """Return the width of the terminal, if present.""" + return dmnsn_terminal_width() + +############ +# Progress # +############ + +cdef class Progress: + cdef dmnsn_progress *_progress + + def __cinit__(self): + self._progress = NULL + + def __init__(self): + raise RuntimeError("attempt to create a Progress object.") + + def __dealloc__(self): + self.finish() + + def finish(self): + if self._progress != NULL: + try: + if dmnsn_finish_progress(self._progress) != 0: + raise RuntimeError("background task failed.") + finally: + self._progress = NULL + + def progress(self): + if self._progress == NULL: + raise RuntimeError("background task finished.") + return dmnsn_get_progress(self._progress) + + def wait(self, progress): + if self._progress == NULL: + raise RuntimeError("background task finished.") + dmnsn_wait_progress(self._progress, progress) + +cdef _Progress(dmnsn_progress *progress): + cdef Progress self = Progress.__new__(Progress) + self._progress = progress + return self + ########## # Timers # ########## @@ -107,7 +149,7 @@ cdef class Vector: elif args[0] == 0: self._v = dmnsn_zero else: - raise TypeError, "expected a sequence or 0" + raise TypeError("expected a sequence or 0") else: self._real_init(*args, **kwargs) @@ -471,14 +513,16 @@ cdef class Canvas: def write_PNG(self, path): """Export the canvas as a PNG file.""" + self.write_PNG_async(path).finish() + def write_PNG_async(self, path): + """Export the canvas as a PNG file, in the background.""" bpath = path.encode("UTF-8") cdef char *cpath = bpath cdef FILE *file = fopen(cpath, "wb") if file == NULL: raise OSError(errno, os.strerror(errno)) - if dmnsn_png_write_canvas(self._canvas, file) != 0: - raise OSError(errno, os.strerror(errno)) + return _Progress(dmnsn_png_write_canvas_async(self._canvas, file)) def draw_GL(self): """Export the canvas to the current OpenGL context.""" @@ -1317,11 +1361,13 @@ cdef class Scene: def raytrace(self): """Render the scene.""" + self.raytrace_async().finish() + def raytrace_async(self): + """Render the scene, in the background.""" # Ensure the default texture is complete cdef Texture default = Texture(Black) dmnsn_texture_cascade(default._texture, &self._scene.default_texture) - - dmnsn_raytrace_scene(self._scene) + return _Progress(dmnsn_raytrace_scene_async(self._scene)) def __dealloc__(self): dmnsn_delete_scene(self._scene) diff --git a/libdimension-python/platform.c b/libdimension-python/platform.c new file mode 100644 index 0000000..30dde93 --- /dev/null +++ b/libdimension-python/platform.c @@ -0,0 +1,41 @@ +/************************************************************************* + * Copyright (C) 2011 Tavian Barnes * + * * + * This file is part of The Dimension Python Module. * + * * + * The Dimension Python Module 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 Dimension Python Module 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 this program. If not, see . * + *************************************************************************/ + +#include "platform.h" +#if HAVE_UNISTD_H + #include +#endif +#if DMNSN_TIOCGWINSZ + #include +#endif + +unsigned int +dmnsn_terminal_width(void) +{ + unsigned int width = 80; + +#if DMNSN_TIOCGWINSZ + struct winsize ws; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) { + width = ws.ws_col; + } +#endif + + return width; +} diff --git a/libdimension-python/platform.h b/libdimension-python/platform.h new file mode 100644 index 0000000..892217a --- /dev/null +++ b/libdimension-python/platform.h @@ -0,0 +1,29 @@ +/************************************************************************* + * Copyright (C) 2011 Tavian Barnes * + * * + * This file is part of The Dimension Python Module. * + * * + * The Dimension Python Module 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 Dimension Python Module 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 this program. If not, see . * + *************************************************************************/ + +#ifndef PLATFORM_H +#define PLATFORM_H + +/** + * Get the width of the terminal. + * @return The width (in characters) of the terminal, defaulting to 80. + */ +unsigned int dmnsn_terminal_width(void); + +#endif /* PLATFORM_H */ -- cgit v1.2.3