Example #1
0
static void on_save_exr (GtkWidget *widget, Explorer* self) {
#ifdef HAVE_EXR
    GtkWidget *dialog;
    GError *error = NULL;
    gchar *filename = NULL;

#if (GTK_CHECK_VERSION(2, 4, 0))
    dialog = gtk_file_chooser_dialog_new ("Save OpenEXR Image",
		                          GTK_WINDOW (glade_xml_get_widget (self->xml, "explorer_window")),
					  GTK_FILE_CHOOSER_ACTION_SAVE,
					  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					  GTK_STOCK_SAVE, GTK_RESPONSE_OK,
					  NULL);
    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
    if (file_location != NULL)
        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), file_location);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
	exr_save_image_file (HISTOGRAM_IMAGER (self->map), filename, &error);

	if (file_location)
	    g_free (file_location);
	file_location = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
    }
#else
    dialog = gtk_file_selection_new ("Save OpenEXR Image");
    gtk_file_selection_set_filename (GTK_FILE_SELECTION (dialog), "rendering.exr");

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
	const gchar *filename;
	filename = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)));
	exr_save_image_file (HISTOGRAM_IMAGER (self->map), filename, &error);
    }
#endif /* GTK_CHECK_VERSION */
    gtk_widget_destroy (dialog);

    if (error) {
	GtkWidget *dialog, *label;
	gchar *text;

	dialog = glade_xml_get_widget (self->xml, "error dialog");
	label = glade_xml_get_widget (self->xml, "error label");

	text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">Could not save \"%s\"</span>\n\n%s", filename, error->message);
	gtk_label_set_markup (GTK_LABEL (label), text);
	g_free (text);
	g_error_free (error);

	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_hide (dialog);
    }

    if (filename)
	g_free (filename);
#endif /* HAVE_EXR */
}
Example #2
0
static void on_load_from_image (GtkWidget *widget, Explorer* self) {
    GtkWidget *dialog, *image;
    GError *error = NULL;
    gchar *filename = NULL;

#if (GTK_CHECK_VERSION(2, 4, 0))
    dialog = gtk_file_chooser_dialog_new ("Open Image Parameters",
		                          GTK_WINDOW (glade_xml_get_widget (self->xml, "explorer_window")),
					  GTK_FILE_CHOOSER_ACTION_OPEN,
					  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					  GTK_STOCK_OPEN, GTK_RESPONSE_OK,
					  NULL);
    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
    image = gtk_image_new ();
    gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), image);
    g_signal_connect (G_OBJECT (dialog), "update-preview", G_CALLBACK (update_image_preview), image);
    if (file_location)
	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), file_location);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
	histogram_imager_load_image_file (HISTOGRAM_IMAGER (self->map), filename, &error);

	if (file_location)
	    g_free (file_location);
	file_location = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
    }
#else
    dialog = gtk_file_selection_new ("Open Image Parameters");

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
	filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog));
	histogram_imager_load_image_file (HISTOGRAM_IMAGER (self->map), filename, &error);
    }
#endif
    gtk_widget_destroy (dialog);

    if (error) {
	GtkWidget *dialog, *label;
	gchar *text;

	dialog = glade_xml_get_widget (self->xml, "error dialog");
	label = glade_xml_get_widget (self->xml, "error label");

	text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">Could not load \"%s\"</span>\n\n%s", filename, error->message);
	gtk_label_set_markup (GTK_LABEL (label), text);
	g_free (text);
	g_error_free (error);

	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_hide (dialog);
    }
    g_free (filename);
}
Example #3
0
static void animation_render_main (IterativeMap *map,
                                   Animation    *animation,
                                   const gchar  *filename,
                                   double        quality) {
    const double frame_rate = 24;
    AnimationIter iter;
    ParameterHolderPair frame;
    guint frame_count = 0;
    gboolean continuation;
    double current_quality;

    AviWriter *avi = avi_writer_new(fopen(filename, "wb"),
                                    HISTOGRAM_IMAGER(map)->width,
                                    HISTOGRAM_IMAGER(map)->height,
                                    frame_rate);

    animation_iter_get_first(animation, &iter);
    frame.a = PARAMETER_HOLDER(de_jong_new());
    frame.b = PARAMETER_HOLDER(de_jong_new());

    while (animation_iter_read_frame(animation, &iter, &frame, frame_rate)) {

        continuation = FALSE;
        do {
            /* Calculate 0.5 seconds between quality updates. This is lower than the
             * batch image rendering default of 2.0 seconds, to better handle
             * lower-quality animations where the individual frames go quicker.
             */
            iterative_map_calculate_motion_timed(map, 0.5, continuation,
                                                 PARAMETER_INTERPOLATOR(parameter_holder_interpolate_linear),
                                                 &frame);
            current_quality = histogram_imager_compute_quality(HISTOGRAM_IMAGER(map));

            printf("\rFrame %d, %e iterations, %.04f quality", frame_count,
                   map->iterations, current_quality);
            fflush(stdout);

            continuation = TRUE;
        } while (current_quality < quality);

        histogram_imager_update_image(HISTOGRAM_IMAGER(map));
        avi_writer_append_frame(avi, HISTOGRAM_IMAGER(map)->image);

        /* Move to the next line for each frame.
         * Updates within a frame overwrite that line.
         */
        printf("\n");

        frame_count++;
    }

    avi_writer_close(avi);
}
Example #4
0
static void       cmd_calc_status      (RemoteServerConn*  self,
					const char*        command,
					const char*        parameters)
{
    if (self->server->verbose)
	printf("[%s:%d]  iterations: %.5e  density: %ld\n",
	       self->gconn->hostname, self->gconn->port,
	       self->map->iterations, HISTOGRAM_IMAGER(self->map)->peak_density);

    remote_server_send_response(self, FYRE_RESPONSE_PROGRESS, "iterations=%.20e density=%ld",
				self->map->iterations, HISTOGRAM_IMAGER(self->map)->peak_density);
}
static void    histogram_merge_callback       (RemoteClient*     self,
					       RemoteResponse*   response,
					       gpointer          user_data)
{
    HistogramImager *dest = HISTOGRAM_IMAGER(user_data);
    double elapsed;

    self->pending_stream_requests--;

    if (self->pending_param_changes) {
	/* This data is for an old parameter set, ignore it.
	 * FIXME: This doesn't distinguish between parameters that
	 *        actaully affect calculation and those that don't.
	 */
	return;
    }

    if (!response->data_length)
	return;

    histogram_imager_merge_stream(dest, response->data, response->data_length);

    /* Update our download speed */
    self->byte_accumulator += response->data_length;
    elapsed = g_timer_elapsed(self->stream_speed_timer, NULL);
    if (elapsed > MINIMUM_SPEED_WINDOW) {
	g_timer_start(self->stream_speed_timer);
	self->bytes_per_sec = self->byte_accumulator / elapsed;
	self->byte_accumulator = 0;
    }
}
static void
histogram_imager_dispose (GObject *gobject)
{
    HistogramImager *self = HISTOGRAM_IMAGER (gobject);

    if (self->histogram) {
	g_free (self->histogram);
	self->histogram = NULL;
    }
    if (self->image) {
	gdk_pixbuf_unref (self->image);
	self->image = NULL;
    }
    if (self->color_table.table) {
	g_free (self->color_table.table);
	self->color_table.table = NULL;
    }
    if (self->color_table.quality) {
	g_free (self->color_table.quality);
	self->color_table.quality = NULL;
    }
    if (self->oversample_tables.linearize) {
	g_free (self->oversample_tables.linearize);
	self->oversample_tables.linearize = NULL;
    }
    if (self->oversample_tables.nonlinearize) {
	g_free (self->oversample_tables.nonlinearize);
	self->oversample_tables.nonlinearize = NULL;
    }

    G_OBJECT_CLASS (parent_class)->dispose (gobject);
}
Example #7
0
static void       cmd_get_histogram_stream (RemoteServerConn*  self,
					    const char*        command,
					    const char*        parameters)
{
    gsize size;

    if (!self->buffer) {
	/* Allocate it with an initial size of 128kB */
	self->buffer_size = 128 * 1024;
	self->buffer = g_malloc(self->buffer_size);
    }

    size = histogram_imager_export_stream(HISTOGRAM_IMAGER(self->map),
					  self->buffer, self->buffer_size);
    remote_server_send_binary(self, self->buffer, size);

    /* If we used more than half the buffer, double its size.
     * This ensures that if we do run out of room, we'll have plenty
     * of space to send the remainder of the buffer next time.
     */
    if (size > (self->buffer_size / 2)) {
	g_free(self->buffer);
	self->buffer_size *= 2;
	self->buffer = g_malloc(self->buffer_size);
    }
}
Example #8
0
static int screensaver_idle_handler(gpointer user_data) {
    ScreenSaver *self = SCREENSAVER(user_data);

    iterative_map_calculate_motion(ITERATIVE_MAP(self->frame_renders[self->current_frame]), 100000,
				   TRUE, PARAMETER_INTERPOLATOR(parameter_holder_interpolate_linear),
				   &self->frame_parameters[self->current_frame]);

    if (GTK_WIDGET_DRAWABLE(self->view)) {

	histogram_view_set_imager(HISTOGRAM_VIEW(self->view),
				  HISTOGRAM_IMAGER(self->frame_renders[self->current_frame]));
	histogram_view_update(HISTOGRAM_VIEW(self->view));

	self->current_frame += self->direction;
	if (self->current_frame >= self->num_frames) {
	    self->current_frame = self->num_frames-2;
	    self->direction = -1;
	}
	if (self->current_frame < 0) {
	    self->current_frame = 1;
	    self->direction = 1;
	}

    }
    return 1;
}
Example #9
0
static gboolean     on_record_change   (gpointer user_data)
{
    Explorer* self = EXPLORER(user_data);

    explorer_append_history(self, history_node_new(HISTOGRAM_IMAGER(self->map)));
    self->history_timer = 0;
    return FALSE;
}
Example #10
0
static gchar*   explorer_strdup_elapsed (Explorer *self)
{
    gulong elapsed = (gulong) histogram_imager_get_elapsed_time(HISTOGRAM_IMAGER(self->map));
    return g_strdup_printf("%02ld:%02ld:%02ld",
			   elapsed / (60*60),
			   (elapsed / 60) % 60,
			   elapsed % 60);
}
Example #11
0
static gchar*   explorer_strdup_quality (Explorer *self)
{
    gdouble q = histogram_imager_compute_quality(HISTOGRAM_IMAGER(self->map));
    if (q > (G_MAXDOUBLE / 2))
	return g_strdup("N/A");
    else
	return g_strdup_printf("%.3f", q);
}
Example #12
0
static void         on_go_forward     (GtkWidget *widget, Explorer *self)
{
    self->history_current_link = self->history_current_link->next;
    explorer_update_history_sensitivity(self);

    self->history_freeze = TRUE;
    history_node_apply(self->history_current_link->data, HISTOGRAM_IMAGER(self->map));
    self->history_freeze = FALSE;
}
Example #13
0
static int animation_render_ui_idle_handler(gpointer user_data) {
    AnimationRenderUi *self = (AnimationRenderUi*) user_data;
    gdouble frame_completion, anim_completion;

    animation_render_ui_run_timed_calculation(self);

    /* Figure out how complete this frame is */
    frame_completion = histogram_imager_compute_quality(HISTOGRAM_IMAGER(self->map)) / self->quality;
    if (frame_completion >= 1) {
	frame_completion = 1;

	/* Write out this frame */
	histogram_imager_update_image(HISTOGRAM_IMAGER(self->map));
	avi_writer_append_frame(self->avi, HISTOGRAM_IMAGER(self->map)->image);

	/* Show the completed frame in our GUI's preview area */
	gtk_image_set_from_pixbuf(GTK_IMAGE(glade_xml_get_widget(self->xml, "preview")),
				  HISTOGRAM_IMAGER(self->map)->image);
	gtk_widget_show(glade_xml_get_widget(self->xml, "preview_frame"));

	/* Move to the next frame */
	if (animation_iter_read_frame(self->animation, &self->iter, &self->frame, self->frame_rate)) {

	    /* We still have more to render, calculate how much we've done so far */
	    self->continuation = FALSE;
	    self->elapsed_anim_time += 1/self->frame_rate;
	    anim_completion = self->elapsed_anim_time / self->anim_length;
	}
	else {
	    /* We're done, yay. Clean up. */
	    anim_completion = 1;
	    animation_render_ui_stop(self);
	}

	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(glade_xml_get_widget(self->xml, "animation_progress")), anim_completion);
    }
    else {
	/* Continue this frame later */
	self->continuation = TRUE;
    }

    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(glade_xml_get_widget(self->xml, "frame_progress")), frame_completion);
    return 1;
}
Example #14
0
static void         on_go_menu_item    (GtkWidget *menu, gpointer user_data)
{
    GList *link = user_data;
    HistoryNode *node = link->data;
    Explorer *self = node->explorer;

    self->history_current_link = link;
    explorer_update_history_sensitivity(self);

    self->history_freeze = TRUE;
    history_node_apply(self->history_current_link->data, HISTOGRAM_IMAGER(self->map));
    self->history_freeze = FALSE;
}
Example #15
0
Explorer* explorer_new(IterativeMap *map, Animation *animation) {
    Explorer *self = EXPLORER(g_object_new(explorer_get_type(), NULL));
    GtkWidget *editor, *window, *scroll;
    GtkRequisition win_req;

    self->animation = ANIMATION(g_object_ref(animation));
    self->map = ITERATIVE_MAP(g_object_ref(map));

    /* Create the parameter editor */
    editor = parameter_editor_new(PARAMETER_HOLDER(map));
    gtk_box_pack_start(GTK_BOX(glade_xml_get_widget(self->xml, "parameter_editor_box")),
		       editor, FALSE, FALSE, 0);
    gtk_widget_show_all(editor);

    /* Create the view */
    self->view = histogram_view_new(HISTOGRAM_IMAGER(map));
    gtk_container_add(GTK_CONTAINER(glade_xml_get_widget(self->xml, "drawing_area_viewport")), self->view);
    gtk_widget_show_all(self->view);

    /* Set the initial render time */
    on_render_time_changed(glade_xml_get_widget(self->xml, "render_time"), self);

    explorer_init_history(self);
    explorer_init_animation(self);
    explorer_init_tools(self);
    explorer_init_cluster(self);
    explorer_init_about(self);

    /* Start the iterative map rendering in the background, and get a callback every time a block
     * of calculations finish so we can update the GUI.
     */
    iterative_map_start_calculation(self->map);
    g_signal_connect(G_OBJECT(self->map), "calculation-finished",
		     G_CALLBACK(on_calculation_finished), self);

    /* Set the window's default size to include our default image size.
     * The cleanest way I know of to do this is to set the scrolled window's scrollbar policies
     * to 'never' and get the window's size requests, set them back to automatic, then set the
     * default size to that size request.
     */
    window = glade_xml_get_widget(self->xml, "explorer_window");
    scroll = glade_xml_get_widget(self->xml, "main_scrolledwindow");
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
    gtk_widget_size_request(window, &win_req);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_window_set_default_size(GTK_WINDOW(window), win_req.width, win_req.height);
    gtk_widget_show(window);

    return self;
}
Example #16
0
static void       gui_init_simple     (RemoteServerConn*     self)
{
    /* Simple GUI, just a window holding our histogram view */
    GtkWidget* view;
    GtkWidget* window;

    view = histogram_view_new(HISTOGRAM_IMAGER(self->map));

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    fyre_set_icon_later(window);
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
    gtk_window_set_title(GTK_WINDOW(window), "Fyre Server");
    gtk_container_add(GTK_CONTAINER(window), view);
    gtk_widget_show_all(window);

    connect_map_to_view(self->map, HISTOGRAM_VIEW(view));

    self->gui = window;
}
Example #17
0
void explorer_update_gui(Explorer *self) {
    /* If the GUI needs updating, update it. This includes limiting the maximum
     * update rate, updating the iteration count display, and actually rendering
     * frames to the drawing area.
     */

    /* If we have rendering changes we're trying to push through as quickly
     * as possible, don't bother with the status bar or with frame rate limiting.
     */
    if (HISTOGRAM_IMAGER(self->map)->render_dirty_flag) {
	histogram_view_update(HISTOGRAM_VIEW(self->view));
	return;
    }

    /* If we have an important status change to report, update both
     * the status bar and the view without frame rate limiting.
     */
    if (self->status_dirty_flag) {
	explorer_update_status_bar(self);
	histogram_view_update(HISTOGRAM_VIEW(self->view));
	return;
    }

    /* Update the status bar at a fixed rate. This will give the user
     * the impression that things are moving along steadily even when
     * we're actually updating the view very slowly later in the render.
     */
    if (!limit_update_rate(self->status_update_rate_timer, 2.0 )) {
	explorer_update_status_bar(self);
    }

    /* Use our funky automatic frame rate adjuster to time normal view updates.
     * This will slow down updates nonlinearly as rendering progresses,
     * to give good interactive response while making batch rendering
     * still fairly efficient.
     */
    if (!explorer_auto_limit_update_rate(self)) {
	histogram_view_update(HISTOGRAM_VIEW(self->view));
    }
}
Example #18
0
ScreenSaver* screensaver_new(IterativeMap *map, Animation *animation) {
    ScreenSaver *self = SCREENSAVER(g_object_new(screensaver_get_type(), NULL));
    int i;
    AnimationIter iter;
    gchar* common_parameters;

    self->animation = ANIMATION(g_object_ref(animation));
    self->map = ITERATIVE_MAP(g_object_ref(map));
    self->view = g_object_ref(histogram_view_new(HISTOGRAM_IMAGER(self->map)));

    /* Allocate and interpolate all frames */
    self->framerate = 10;
    self->num_frames = animation_get_length(self->animation) * self->framerate;
    self->frame_renders = g_new0(IterativeMap*, self->num_frames);
    self->frame_parameters = g_new0(ParameterHolderPair, self->num_frames);
    self->current_frame = 0;
    common_parameters = parameter_holder_save_string(PARAMETER_HOLDER(map));

    animation_iter_seek(animation, &iter, 0);
    for (i=0; i<self->num_frames; i++) {
	self->frame_renders[i] = ITERATIVE_MAP(de_jong_new());
	parameter_holder_load_string(PARAMETER_HOLDER(self->frame_renders[i]), common_parameters);

	self->frame_parameters[i].a = PARAMETER_HOLDER(de_jong_new());
	animation_iter_load(animation, &iter, self->frame_parameters[i].a);
	animation_iter_seek_relative(animation, &iter, 1/self->framerate);
    }
    for (i=0; i<self->num_frames-1; i++)
	self->frame_parameters[i].b = self->frame_parameters[i+1].a;
    self->frame_parameters[self->num_frames-1].b = self->frame_parameters[self->num_frames-1].a;

    g_free(common_parameters);
    self->direction = 1;

    screensaver_start(self);
    return self;
}
Example #19
0
static gboolean explorer_auto_limit_update_rate(Explorer *self) {
    /* Automatically determine a good maximum frame rate based on the current
     * elapsed time, and use limit_update_rate() to limit us to that.
     * Returns 1 if a frame should not be rendered.
     *
     * 'gamma' determines the nonlinearity. At gamma=1 we ramp down the period
     * linearly. (not the rate) The other parameters determine the speed and the
     * maximum/minimum rates. Voodoo below!
     */

    const double initial_rate = 60;
    const double final_rate = 0.1;
    const double ramp_down_seconds = 120;
    const double gamma = 0.9;

    /* Convert the user-friendly constants above into constants in nonlinear period space */
    double rate, elapsed;
    static gboolean init = FALSE;
    static double pow_initial_period, pow_period_scale, one_over_gamma;
    if (!init) {
	pow_initial_period = pow(1.0 / initial_rate, gamma);
	pow_period_scale = (pow(1.0 / final_rate, gamma) - pow_initial_period) / ramp_down_seconds;
	one_over_gamma = 1.0 / gamma;
	init = TRUE;
    }

    /* Now it's just a simple linear function followed by a nonlinear
     * transformation back to rate space.
     */
    elapsed = histogram_imager_get_elapsed_time(HISTOGRAM_IMAGER(self->map));
    if (elapsed > ramp_down_seconds)
	rate = final_rate;
    else
	rate = 1.0 / pow(pow_initial_period + pow_period_scale * elapsed, one_over_gamma);

    return limit_update_rate(self->auto_update_rate_timer, rate);
}
Example #20
0
static void cell_renderer_bifurcation_render(GtkCellRenderer      *cell,
					     GdkWindow            *window,
					     GtkWidget            *widget,
					     GdkRectangle         *background_area,
					     GdkRectangle         *cell_area,
					     GdkRectangle         *expose_area,
					     GtkCellRendererState  flags) {
    CellRendererBifurcation *self = CELL_RENDERER_BIFURCATION(cell);
    BifurcationDiagram *bd = get_bifurcation_diagram(self);
    GtkStateType state;
    RedrawInfo *nr;

    if (!bd)
	return;

    /* Determine the correct state to render our text in, based on
     * the cell's selectedness and the widget's current state.
     * This was copied from GtkCellRendererText.
     */
    if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) {
	if (GTK_WIDGET_HAS_FOCUS (widget))
	    state = GTK_STATE_SELECTED;
	else
	    state = GTK_STATE_ACTIVE;
    }
    else {
	if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE)
	    state = GTK_STATE_INSENSITIVE;
	else
	    state = GTK_STATE_NORMAL;
    }

    /* Set the bifurcation diagram renderer's parameters appropriately for this
     * cell renderer. It will automatically figure out what if anything it has
     * to change internally. We size it to fit this cell exactly, and set
     * the colors appropriately for our state and theme.
     */
    g_object_set(bd,
		 "width",  cell_area->width,
		 "height", cell_area->height,
		 "fgcolor-gdk", &GTK_WIDGET(widget)->style->fg[state],
		 "bgcolor-gdk", &GTK_WIDGET(widget)->style->base[state],
		 NULL);

    /* Assume that 5*(cell area) is good enough) */
    if(HISTOGRAM_IMAGER(bd)->total_points_plotted > 5 * cell_area->width * cell_area->height) {
        gdk_draw_pixbuf(window, GTK_WIDGET(widget)->style->fg_gc[state],
		        HISTOGRAM_IMAGER(bd)->image,
		        0, 0, cell_area->x, cell_area->y, cell_area->width, cell_area->height,
		        GDK_RGB_DITHER_NONE, 0, 0);

        return;
    }

    /* Render it a bit and update the image */
    bifurcation_diagram_calculate(bd, 10000, 100);
    histogram_imager_update_image(HISTOGRAM_IMAGER(bd));

    gdk_draw_pixbuf(window, GTK_WIDGET(widget)->style->fg_gc[state],
		    HISTOGRAM_IMAGER(bd)->image,
		    0, 0, cell_area->x, cell_area->y, cell_area->width, cell_area->height,
		    GDK_RGB_DITHER_NONE, 0, 0);

    nr = g_new (RedrawInfo, 1);
    nr->view = self->tree;
    nr->rect.x = cell_area->x;
    nr->rect.y = cell_area->y;
    nr->rect.width = cell_area->width;
    nr->rect.height = cell_area->height;

    g_timeout_add (20, (GSourceFunc) cell_queue_redraw, nr);
}
static void
histogram_imager_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
    HistogramImager *self = HISTOGRAM_IMAGER(object);
    GdkColor gdkc;

    switch (prop_id) {

    case PROP_WIDTH:
	update_uint_if_necessary (g_value_get_uint (value), &self->size_dirty_flag, &self->width);
	break;

    case PROP_HEIGHT:
	update_uint_if_necessary (g_value_get_uint (value), &self->size_dirty_flag, &self->height);
	break;

    case PROP_OVERSAMPLE:
	if (update_uint_if_necessary (g_value_get_uint (value), &self->size_dirty_flag, &self->oversample))
	    g_object_notify (object, "oversample-enabled");
	break;

    case PROP_SIZE:
	histogram_imager_resize_from_string (self, g_value_get_string (value));
	break;

    case PROP_EXPOSURE:
	update_double_if_necessary (g_value_get_double (value), &self->render_dirty_flag, &self->exposure, 0.00009);
	break;

    case PROP_GAMMA:
	update_double_if_necessary (g_value_get_double (value), &self->render_dirty_flag, &self->gamma, 0.00009);
	break;

    case PROP_OVERSAMPLE_GAMMA:
	update_double_if_necessary (g_value_get_double (value), &self->render_dirty_flag, &self->oversample_gamma, 0.00009);
	break;

    case PROP_FGCOLOR:
	/* Convert to a GdkColor and set the fgcolor-gdk property. This is necessary
	 * so that notify signals attached to fgcolor-gdk are sent properly, and in
	 * general makes it cleaner.
	 */
	gdk_color_parse (g_value_get_string (value), &gdkc);
	g_object_set (self, "fgcolor-gdk", &gdkc, NULL);
	break;

    case PROP_BGCOLOR:
	/* And the same goes for background... */
	gdk_color_parse (g_value_get_string (value), &gdkc);
	g_object_set (self, "bgcolor-gdk", &gdkc, NULL);
	break;

    case PROP_FGCOLOR_GDK:
	update_color_if_necessary ((GdkColor*) g_value_get_boxed (value), &self->render_dirty_flag, &self->fgcolor);
	break;

    case PROP_BGCOLOR_GDK:
	update_color_if_necessary ((GdkColor*) g_value_get_boxed (value), &self->render_dirty_flag, &self->bgcolor);
	break;

    case PROP_FGALPHA:
	update_uint_if_necessary (g_value_get_uint (value), &self->render_dirty_flag, &self->fgalpha);
	break;

    case PROP_BGALPHA:
	update_uint_if_necessary (g_value_get_uint (value), &self->render_dirty_flag, &self->bgalpha);
	break;

    case PROP_CLAMPED:
	update_boolean_if_necessary (g_value_get_boolean (value), &self->render_dirty_flag, &self->clamped);
	break;

    default:
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
	break;
    }
}
Example #22
0
static void         on_go_menu_show    (GtkWidget *menu, Explorer *self)
{
    const int max_linear_items = 4;
    const int max_scaled_items = 10;
    int i, num_scaled_items;
    GList *current;
    gdouble t_total, t;
    GTimeVal *scaled_reference;
    HistoryNode* node;
    explorer_cleanup_go_items(self);

    /* If our queue is empty, add a new record immediately. This
     * will prevent us from getting an empty 'go' menu right after
     * startup- instead it will have a thumbnail of our defaults
     * or whatever image the user happened to load. This can't
     * go in our initialization above since that happens before
     * we've actually rendered anything. Putting it here is more
     * reliable than using a timer.
     */
    if (self->history_queue->length < 1)
	explorer_append_history(self, history_node_new(HISTOGRAM_IMAGER(self->map)));

    /* The first few items are straight from the most recent list */
    current = g_queue_peek_tail_link(self->history_queue);
    for (i=0; i<max_linear_items; i++) {
	if (!current)
	    return;
	explorer_add_go_item(self, current);
	current = current->prev;
    }

    /* The rest of the list is spread evenly over time, from the end
     * of the above section back to the oldest history we have.
     */
    if (!current)
	return;
    node = current->data;
    scaled_reference = &node->timestamp;
    t_total = timeval_subtract(scaled_reference,
			       &((HistoryNode*)g_queue_peek_head(self->history_queue))->timestamp);
    num_scaled_items = MIN(self->history_queue->length - max_linear_items,
			   max_scaled_items);
    if (num_scaled_items <= 0)
	return;

    for (i=0; i<num_scaled_items; i++) {

	/* For each item on the scaled_items list, find the
	 * node at the proper position in time.
	 */
	while (1) {
	    if (!current)
		return;

	    node = current->data;
	    t  = timeval_subtract(scaled_reference, &node->timestamp);

	    if (t > (i*t_total/num_scaled_items))
		break;
	    current = current->prev;
	}

	explorer_add_go_item(self, current);
    }
}
Example #23
0
int main(int argc, char ** argv) {
    IterativeMap* map;
    Animation* animation;
    gboolean animate = FALSE;
    gboolean have_gtk;
    gboolean verbose = FALSE;
    gboolean hidden = FALSE;
    enum {INTERACTIVE, RENDER, SCREENSAVER, REMOTE} mode = INTERACTIVE;
    const gchar *outputFile = NULL;
    const gchar *pidfile = NULL;
    int c, option_index=0;
    double quality = 1.0;
#ifdef HAVE_GNET
    int port_number = FYRE_DEFAULT_PORT;
#endif
    GError *error = NULL;

    math_init();
    g_type_init();
    have_gtk = gtk_init_check(&argc, &argv);

#ifdef HAVE_GNET
    gnet_init();
#  ifdef WIN32
    gnet_ipv6_set_policy(GIPV6_POLICY_IPV4_ONLY);
#  endif
#endif

    map = ITERATIVE_MAP(de_jong_new());
    animation = animation_new();

    while (1) {
        static struct option long_options[] = {
            {"help",         0, NULL, 'h'},
            {"read",         1, NULL, 'i'},
            {"animate",      1, NULL, 'n'},
            {"output",       1, NULL, 'o'},
            {"param",        1, NULL, 'p'},
            {"size",         1, NULL, 's'},
            {"oversample",   1, NULL, 'S'},
            {"quality",      1, NULL, 'q'},
            {"remote",       0, NULL, 'r'},
            {"verbose",      0, NULL, 'v'},
            {"port",         1, NULL, 'P'},
            {"cluster",      1, NULL, 'c'},
            {"auto-cluster", 0, NULL, 'C'},
            {"screensaver",  0, NULL, 1000},   /* Undocumented, still experimental */
            {"hidden",       0, NULL, 1001},
            {"chdir",        1, NULL, 1002},   /* Undocumented, used by win32 file associations */
            {"pidfile",      1, NULL, 1003},
            {"version",      0, NULL, 1004},
            {NULL},
        };
        c = getopt_long(argc, argv, "hi:n:o:p:s:S:q:rvP:c:C",
                        long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {

        case 'i':
        {
            histogram_imager_load_image_file(HISTOGRAM_IMAGER(map), optarg, &error);
            break;
        }

        case 'n':
        {
            GtkTreeIter iter;

            animation_load_file(animation, optarg);
            animate = TRUE;
            gtk_tree_model_get_iter_first(GTK_TREE_MODEL(animation->model), &iter);
            animation_keyframe_load(animation, &iter, PARAMETER_HOLDER(map));
            break;
        }

        case 'o':
            mode = RENDER;
            outputFile = optarg;
            break;

        case 'p':
            parameter_holder_load_string(PARAMETER_HOLDER(map), optarg);
            break;

        case 's':
            parameter_holder_set(PARAMETER_HOLDER(map), "size" , optarg);
            break;

        case 'S':
            parameter_holder_set(PARAMETER_HOLDER(map), "oversample", optarg);
            break;

        case 'q':
            quality = atof(optarg);
            break;

        case 'v':
            verbose = TRUE;
            break;

#ifdef HAVE_GNET
        case 'c':
        {
            ClusterModel *cluster = cluster_model_get(map, TRUE);
            cluster_model_add_nodes(cluster, optarg);
        }
        break;
        case 'C':
        {
            ClusterModel *cluster = cluster_model_get(map, TRUE);
            cluster_model_enable_discovery(cluster);
        }
        break;
        case 'r':
            mode = REMOTE;
            break;
        case 'P':
            port_number = atol(optarg);
            break;
#else
        case 'c':
        case 'C':
        case 'P':
            fprintf(stderr,
                    "This Fyre binary was compiled without gnet support.\n"
                    "Cluster support is not available.\n");
            break;
        case 'r':
            fprintf(stderr,
                    "This Fyre binary was compiled without gnet support.\n"
                    "Cluster support is not available.\n");
            exit(1);
            break;
#endif

        case 1000: /* --screensaver */
            mode = SCREENSAVER;
            break;

        case 1001: /* --hidden */
            hidden = TRUE;
            break;

        case 1002: /* --chdir */
            chdir(optarg);
            break;

        case 1003: /* --pidfile */
            pidfile = optarg;
            break;

        case 1004: /* --version */
            printf("%s\n", VERSION);
            return 0;

        case 'h':
        default:
            usage(argv);
            return 1;
        }
    }

    if (optind + 1 < argc) {
        usage(argv);
        return 1;
    }

    if (optind != argc) {
        char *ext = strrchr (argv[optind], '.');
        if (ext) {
            if (g_strcasecmp(ext, ".png") == 0) {
                histogram_imager_load_image_file(HISTOGRAM_IMAGER(map), argv[optind], &error);
            } else if (g_strcasecmp(ext, ".fa") == 0) {
                GtkTreeIter iter;

                animation_load_file(animation, argv[optind]);
                animate = TRUE;
                gtk_tree_model_get_iter_first(GTK_TREE_MODEL(animation->model), &iter);
                animation_keyframe_load(animation, &iter, PARAMETER_HOLDER(map));
            } else {
                usage(argv);
                return 1;
            }
        } else {
            usage(argv);
            return 1;
        }
    }

    switch (mode) {

    case INTERACTIVE: {
        Explorer *explorer;

        if (!have_gtk) {
            fprintf(stderr, "GTK intiailization failed, can't start in interactive mode\n");
            return 1;
        }
        explorer = explorer_new (map, animation);
        if (error) {
            GtkWidget *dialog, *label;
            gchar *text;

            dialog = glade_xml_get_widget (explorer->xml, "error dialog");
            label = glade_xml_get_widget (explorer->xml, "error label");

            text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">Error!</span>\n\n%s", error->message);
            gtk_label_set_markup (GTK_LABEL (label), text);
            g_free (text);
            g_error_free (error);

            gtk_dialog_run (GTK_DIALOG (dialog));
            gtk_widget_hide (dialog);
        }
        gtk_main();
        break;
    }

    case RENDER: {
        acquire_console();
        if (error) {
            g_print ("Error: %s\n", error->message);
            g_error_free (error);
        }
        if (animate)
            animation_render_main (map, animation, outputFile, quality);
        else
            batch_image_render (map, outputFile, quality);
        break;
    }

    case REMOTE: {
#ifdef HAVE_GNET
        if (verbose) {
            acquire_console();
        }
        else {
            daemonize_to_pidfile(pidfile);
        }
        if (!hidden)
            discovery_server_new(FYRE_DEFAULT_SERVICE, port_number);
        remote_server_main_loop(port_number, have_gtk, verbose);
#else
        fprintf(stderr,
                "This Fyre binary was compiled without gnet support.\n"
                "Remote control mode is not available.\n");
#endif
        break;
    }

    case SCREENSAVER: {
        ScreenSaver* screensaver;
        GtkWidget* window;

        if (!have_gtk) {
            fprintf(stderr, "GTK intiailization failed, can't start in screensaver mode\n");
            return 1;
        }

        screensaver = screensaver_new(map, animation);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        fyre_set_icon_later(window);
        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
        gtk_window_set_title(GTK_WINDOW(window), "Fyre Screensaver");
        gtk_container_add(GTK_CONTAINER(window), screensaver->view);
        gtk_widget_show_all(window);

        gtk_main();
        break;
    }
    }

    return 0;
}
static void
histogram_imager_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
    HistogramImager *self = HISTOGRAM_IMAGER (object);

    switch (prop_id) {

    case PROP_WIDTH:
	g_value_set_uint (value, self->width);
	break;

    case PROP_HEIGHT:
	g_value_set_uint (value, self->height);
	break;

    case PROP_OVERSAMPLE:
	g_value_set_uint (value, self->oversample);
	break;

    case PROP_OVERSAMPLE_ENABLED:
	g_value_set_boolean (value, self->oversample > 1);
	break;

    case PROP_CLAMPED:
	g_value_set_boolean (value, self->clamped);
	break;

    case PROP_EXPOSURE:
	g_value_set_double (value, self->exposure);
	break;

    case PROP_GAMMA:
	g_value_set_double (value, self->gamma);
	break;

    case PROP_OVERSAMPLE_GAMMA:
	g_value_set_double (value, self->oversample_gamma);
	break;

    case PROP_FGALPHA:
	g_value_set_uint (value, self->fgalpha);
	break;

    case PROP_BGALPHA:
	g_value_set_uint (value, self->bgalpha);
	break;

    case PROP_SIZE:
	g_value_set_string_take_ownership (value, g_strdup_printf ("%dx%d", self->width, self->height));
	break;

    case PROP_FGCOLOR:
	g_value_set_string_take_ownership (value, describe_color (&self->fgcolor));
	break;

    case PROP_BGCOLOR:
	g_value_set_string_take_ownership (value, describe_color (&self->bgcolor));
	break;

    case PROP_FGCOLOR_GDK:
	g_value_set_boxed (value, &self->fgcolor);
	break;

    case PROP_BGCOLOR_GDK:
	g_value_set_boxed (value, &self->bgcolor);
	break;

    default:
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
	break;
    }
}
HistogramImager*
histogram_imager_new ()
{
    return HISTOGRAM_IMAGER (g_object_new (histogram_imager_get_type (), NULL));
}