예제 #1
0
/**
 * ppg_visualizer_set_is_important:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Sets if this visualizer is important. Important visualizers can be shown
 * when an instrument is collaposed into its tiny view.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_set_is_important (PpgVisualizer *visualizer,
                                 gboolean       important)
{
	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	visualizer->priv->important = important;
	g_object_notify(G_OBJECT(visualizer), "is-important");
}
예제 #2
0
/**
 * ppg_visualizer_set_end_time:
 * @visualizer: (in): A #PpgVisualizer.
 * @end_time: (in): A #gdouble containing the new end time.
 *
 * Sets the end_time for the visualizer. A new draw request is queued.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_set_end_time (PpgVisualizer *visualizer,
                             gdouble        end_time)
{
	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
	g_return_if_fail(end_time >= 0.0);

	visualizer->priv->end_time = end_time;
	ppg_visualizer_queue_draw(visualizer);
}
예제 #3
0
/**
 * ppg_visualizer_set_title:
 * @visualizer: (in): A #PpgVisualizer.
 * @title: (in): A string containing the visualizer title.
 *
 * Sets the title for the visualizer as viewd by the user.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_visualizer_set_title (PpgVisualizer *visualizer,
                          const gchar   *title)
{
	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
	g_return_if_fail(visualizer->priv->title == NULL);

	visualizer->priv->title = g_strdup(title);
	g_object_notify(G_OBJECT(visualizer), "title");
}
예제 #4
0
static void
ppg_instrument_visualizer_added (PpgInstrument *instrument,
                                 PpgVisualizer *visualizer)
{
	PpgInstrumentPrivate *priv;

	g_return_if_fail(PPG_IS_INSTRUMENT(instrument));
	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	priv = instrument->priv;
	priv->visualizers = g_list_prepend(priv->visualizers, visualizer);
}
예제 #5
0
/**
 * ppg_visualizer_thaw:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Thaws a call to ppg_visualizer_freeze() and queues a new draw request of
 * the visualizer.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_thaw (PpgVisualizer *visualizer)
{
	PpgVisualizerPrivate *priv;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	priv = visualizer->priv;

	priv->frozen = FALSE;
	ppg_visualizer_queue_draw(visualizer);
}
예제 #6
0
/**
 * ppg_visualizer_set_natural_height:
 * @visualizer: (in): A #PpgVisualizer.
 * @natural_height: (in): The natural height of the visualizer.
 *
 * Sets the natural height for the visualizer. This is what most
 * implementations will want to modify if they need to adjust their
 * height based on the content. The zoom level in the instrument
 * will be multiplied against this value to get the effective
 * height for the visualizer.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_visualizer_set_natural_height (PpgVisualizer *visualizer,
                                   gdouble        natural_height)
{
	PpgVisualizerPrivate *priv;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	priv = visualizer->priv;

	priv->natural_height = natural_height;
	g_object_notify(G_OBJECT(visualizer), "natural-height");
}
예제 #7
0
/**
 * ppg_visualizer_queue_resize:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Queues a request to resize the pattern the visualizer uses to render.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_visualizer_queue_resize (PpgVisualizer *visualizer)
{
	PpgVisualizerPrivate *priv;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	priv = visualizer->priv;

	if (!priv->resize_handler) {
		priv->resize_handler = g_timeout_add(0, ppg_visualizer_resize_timeout,
		                                     visualizer);
	}
}
예제 #8
0
/**
 * ppg_visualizer_freeze:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Freezes the visualizer preventing it from drawing updates. Drawing will
 * continue when ppg_visualizer_thaw() is called.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_freeze (PpgVisualizer *visualizer)
{
	PpgVisualizerPrivate *priv;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	priv = visualizer->priv;

	priv->frozen = TRUE;
	if (priv->draw_handler) {
		g_source_remove(priv->draw_handler);
		priv->draw_handler = 0;
		priv->draw_begin_time = 0.0;
		priv->draw_end_time = 0.0;
	}
}
예제 #9
0
/**
 * ppg_visualizer_resize_timeout:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * A GSourceFunc to handle a resize request. The surface of the visualizer
 * is resized and a draw request is queued.
 *
 * Returns: %FALSE always
 * Side effects: None.
 */
static gboolean
ppg_visualizer_resize_timeout (gpointer data)
{
	PpgVisualizer *visualizer = (PpgVisualizer *)data;
	PpgVisualizerPrivate *priv;
	cairo_pattern_t *pattern;
	GdkWindow *window;
	GooCanvas *canvas;
	gdouble width;
	gdouble height;

	g_return_val_if_fail(PPG_IS_VISUALIZER(visualizer), FALSE);

	priv = visualizer->priv;

	/*
	 * Remove existing surface.
	 */
	if (priv->surface) {
		g_object_set(visualizer, "pattern", NULL, NULL);
		cairo_surface_destroy(priv->surface);
		priv->surface = NULL;
	}

	/*
	 * Create new surface matching new size allocation.
	 */
	g_object_get(visualizer, "height", &height, "width", &width, NULL);
	canvas = goo_canvas_item_get_canvas(GOO_CANVAS_ITEM(visualizer));
	window = gtk_widget_get_window(GTK_WIDGET(canvas));
	priv->surface = gdk_window_create_similar_surface(window,
	                                                  CAIRO_CONTENT_COLOR_ALPHA,
	                                                  width, height);

	/*
	 * Create a new pattern for drawing the item.
	 */
	pattern = cairo_pattern_create_for_surface(priv->surface);
	g_object_set(visualizer, "pattern", pattern, NULL);
	cairo_pattern_destroy(pattern);
	ppg_visualizer_queue_draw(visualizer);

	priv->resize_handler = 0;
	return FALSE;
}
예제 #10
0
/**
 * ppg_visualizer_set_time:
 * @visualizer: (in): A #PpgVisualizer.
 * @begin_time: (in): A #gdouble containing the new begin time.
 * @end_time: (in): A #gdouble containing the new end time.
 *
 * Sets both the begin_time and end_time for the visualizer. A new draw
 * request is queued.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_set_time (PpgVisualizer *visualizer,
                         gdouble        begin_time,
                         gdouble        end_time)
{
	PpgVisualizerPrivate *priv;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
	g_return_if_fail(begin_time >= 0.0);
	g_return_if_fail(end_time >= begin_time);

	priv = visualizer->priv;

	if ((priv->begin_time != begin_time) || (priv->end_time != end_time)) {
		priv->begin_time = begin_time;
		priv->end_time = end_time;
		ppg_visualizer_queue_draw(visualizer);
	}
}
예제 #11
0
void
ppg_instrument_remove_visualizer (PpgInstrument *instrument,
                                  PpgVisualizer *visualizer)
{
	PpgInstrumentPrivate *priv;

	g_return_if_fail(PPG_IS_INSTRUMENT(instrument));
	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));

	priv = instrument->priv;

	if (!g_list_find(priv->visualizers, visualizer)) {
		g_critical("Instrument does not contain visualizer instance!");
		return;
	}

	priv->visualizers = g_list_remove(priv->visualizers, visualizer);
	g_signal_emit(instrument, signals[VISUALIZER_REMOVED], 0, visualizer);
}
예제 #12
0
/**
 * ppg_visualizer_queue_draw_time_span:
 * @visualizer: (in): A #PpgVisualizer.
 * @begin_time: (in): A #gdouble contianing the beggining time.
 * @end_time: (in): A #gdouble contianing the ending time.
 *
 * Queues a draw for a particular time span. If @begin_time and #end_time
 * are 0.0, then the entire visibile area will be drawn.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_queue_draw_time_span (PpgVisualizer *visualizer,
                                     gdouble        begin_time,
                                     gdouble        end_time,
                                     gboolean       now)
{
	PpgVisualizerPrivate *priv;
	guint msec;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
	g_return_if_fail(begin_time >= 0.0);
	g_return_if_fail(end_time >= 0.0);

	priv = visualizer->priv;

	if (begin_time == 0.0) {
		begin_time = priv->begin_time;
	}

	if (end_time == 0.0) {
		end_time = priv->end_time;
	}

	if (!priv->frozen) {
		if (now) {
			priv->draw_begin_time = begin_time;
			priv->draw_end_time = end_time;
			ppg_visualizer_draw_timeout(visualizer);
		} else if (!priv->draw_handler) {
			msec = 1000 / priv->frame_limit;
			priv->draw_begin_time = begin_time;
			priv->draw_end_time = end_time;
			priv->draw_handler = g_timeout_add(msec,
			                                   ppg_visualizer_draw_timeout,
			                                   visualizer);
		} else {
			priv->draw_begin_time = MIN(priv->draw_begin_time, begin_time);
			priv->draw_end_time = MAX(priv->draw_end_time, end_time);
		}
	}
}
예제 #13
0
/**
 * ppg_instrument_view_visualizer_added:
 * @view: (in): A #PpgInstrumentView.
 *
 * Handle the "visualizer-added" event for the #PpgInstrument. Add the
 * visualizer to our table of visualizers.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_instrument_view_visualizer_added (PpgInstrumentView *view,
                                      PpgVisualizer     *visualizer,
                                      PpgInstrument     *instrument)
{
    PpgInstrumentViewPrivate *priv;
    GooCanvasItem *item = (GooCanvasItem *)visualizer;
    gdouble width;

    g_return_if_fail(PPG_IS_INSTRUMENT_VIEW(view));
    g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
    g_return_if_fail(PPG_IS_INSTRUMENT(instrument));

    priv = view->priv;

    g_object_get(view, "width", &width, NULL);
    width = MAX(200.0, width - HEADER_WIDTH);
    g_object_set(item,
                 "parent", priv->table,
                 "width", width,
                 "visibility", GOO_CANVAS_ITEM_VISIBLE,
                 NULL);
    g_object_bind_property_full(view, "width", item, "width", 0,
                                ppg_instrument_view_transform_width,
                                NULL, NULL, NULL);
    goo_canvas_item_set_child_properties(priv->table, item,
                                         "bottom-padding", ROW_SPACING,
                                         "column", 0,
                                         "row", priv->visualizers->len,
                                         NULL);
    g_ptr_array_add(priv->visualizers, visualizer);
    g_signal_connect_swapped(visualizer, "notify::natural-height",
                             G_CALLBACK(ppg_instrument_view_notify_natural_height),
                             view);
    ppg_instrument_view_relayout(view);
}
예제 #14
0
/**
 * ppg_visualizer_task_notify_state:
 * @visualizer: (in): A #PpgVisualizer.
 * @pspec: (in): A #GParamSpec.
 * @task: (in): A #PpgTask.
 *
 * Handle the "notify::state" signal from @task. Update the visualizer
 * pattern if necessary.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_visualizer_task_notify_state (PpgVisualizer *visualizer,
                                  GParamSpec    *pspec,
                                  PpgTask       *task)
{
	PpgVisualizerPrivate *priv;
	cairo_surface_t *surface;
	PpgTaskState state;
	cairo_t *cr;
	gdouble begin_time;
	gdouble height;
	gdouble total_width;
	gdouble span;
	gdouble width;
	gdouble x;
	gdouble y;

	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
	g_return_if_fail(PPG_IS_TASK(task));
	g_return_if_fail(visualizer->priv->surface);

	priv = visualizer->priv;

	/*
	 * We don't own the reference, so safe to just drop our pointer. Using
	 * GObjects weak pointers here would be a lot of maintenance pain.
	 */
	if (priv->task == task) {
		priv->task = NULL;
	}

	g_object_get(task,
	             "state", &state,
	             "surface", &surface,
	             NULL);

	if (state == PPG_TASK_SUCCESS) {
		g_object_get(task,
		             "begin-time", &begin_time,
		             "height", &height,
		             "width", &width,
		             "x", &x,
		             "y", &y,
		             NULL);

		span = priv->end_time - priv->begin_time;
		g_object_get(visualizer, "width", &total_width, NULL);
		x = (begin_time - priv->begin_time) / span * total_width;

		/*
		 * Only draw what we can do on integer aligned offsets.
		 *
		 * TODO: We need to make sure we render extra area to prevent
		 *       a striping effect.
		 */
		width -= ceil(x) - x;
		x = ceil(x);

		cr = cairo_create(priv->surface);
		cairo_set_source_surface(cr, surface, x, y);
		if (cairo_status(cr) != 0) {
			cairo_destroy(cr);
			GOTO(failure);
		}

		/*
		 * Clip the range of the draw.
		 */
		cairo_rectangle(cr, x, y, width, height);
		cairo_clip_preserve(cr);

		/*
		 * Clear the draw area.
		 */
		cairo_save(cr);
		cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
		cairo_fill_preserve(cr);
		cairo_restore(cr);

		/*
		 * Fill in the rendered image.
		 */
		cairo_fill(cr);
		cairo_destroy(cr);

		goo_canvas_item_request_update(GOO_CANVAS_ITEM(visualizer));
	}

  failure:
	/*
	 * Release our surface that was allocated for the draw request.
	 */
	if ((state & PPG_TASK_FINISHED_MASK) != 0) {
		cairo_surface_destroy(surface);
	}
}
예제 #15
0
/**
 * ppg_visualizer_get_name:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Retrieves the name of a visualizer.
 *
 * Returns: None.
 * Side effects: None.
 */
const gchar*
ppg_visualizer_get_name (PpgVisualizer *visualizer)
{
	g_return_val_if_fail(PPG_IS_VISUALIZER(visualizer), NULL);
	return visualizer->priv->name;
}
예제 #16
0
/**
 * ppg_visualizer_draw_timeout:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * A GSourceFunc to start a new drawing task.
 *
 * Returns: %FALSE always.
 * Side effects: None.
 */
static gboolean
ppg_visualizer_draw_timeout (gpointer data)
{
	PpgVisualizer *visualizer = (PpgVisualizer *)data;
	PpgVisualizerPrivate *priv;
	cairo_surface_t *surface = NULL;
	gpointer instance;
	gdouble begin_time;
	gdouble end_time;
	gdouble height;
	gdouble span;
	gdouble width;
	gdouble x;

	g_return_val_if_fail(PPG_IS_VISUALIZER(visualizer), FALSE);

	priv = visualizer->priv;

	/*
	 * Cancel any active tasks. The task will lose its reference after
	 * the task scheduler completes; so we can just NULL it out.
	 */
	if ((instance = priv->task)) {
		priv->task = NULL;
		ppg_task_cancel(instance);
	}

	/*
	 * Make sure we have a time range to even render.
	 */
	if (priv->begin_time == 0.0 && priv->end_time == 0.0) {
		goto cleanup;
	}

	/*
	 * Get the time range for the render.
	 */
	begin_time = CLAMP(priv->draw_begin_time, 0.0, priv->end_time);
	end_time = CLAMP(priv->draw_end_time, 0.0, priv->end_time);
	if (begin_time == 0.0 && end_time == 0.0) {
		begin_time = priv->begin_time;
		end_time = priv->end_time;
	}

	/*
	 * Get the area for the render. This could probably be optimized to
	 * remove the division by keeping a ratio of (time range / width).
	 */
	g_object_get(visualizer, "height", &height, "width", &width, NULL);
	span = priv->end_time - priv->begin_time;
	x = (begin_time - priv->begin_time) / span * width;
	width = ((end_time - priv->begin_time) / span * width) - x;

	/*
	 * Create a surface for the rendering.
	 */
	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
	                                     width, height);

	/*
	 * Create the task to do the rendering.
	 */
	priv->task = PPG_VISUALIZER_GET_CLASS(visualizer)->
		draw(visualizer,
	         cairo_surface_reference(surface),
	         begin_time, end_time,
	         0, 0, width, height);
	g_signal_connect_swapped(priv->task, "notify::state",
	                         G_CALLBACK(ppg_visualizer_task_notify_state),
	                         visualizer);
	ppg_task_schedule(priv->task);

  cleanup:
	if (surface) {
		cairo_surface_destroy(surface);
	}
	priv->draw_handler = 0;
	priv->draw_begin_time = 0.0;
	priv->draw_end_time = 0.0;

	return FALSE;
}
예제 #17
0
/**
 * ppg_visualizer_queue_draw:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Queues a draw request for the entire visible area of the visualizer.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_visualizer_queue_draw (PpgVisualizer *visualizer)
{
	g_return_if_fail(PPG_IS_VISUALIZER(visualizer));
	ppg_visualizer_queue_draw_time_span(visualizer, 0.0, 0.0, TRUE);
}
예제 #18
0
/**
 * ppg_visualizer_get_is_important:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Retrieves if this visualizer is important. See
 * ppg_visualizer_set_is_important() for more information.
 *
 * Returns: %TRUE if the visualizer is important.
 * Side effects: None.
 */
gboolean
ppg_visualizer_get_is_important (PpgVisualizer *visualizer)
{
	g_return_val_if_fail(PPG_IS_VISUALIZER(visualizer), FALSE);
	return visualizer->priv->important;
}
예제 #19
0
/**
 * ppg_visualizer_get_natural_height:
 * @visualizer: (in): A #PpgVisualizer.
 *
 * Gets the natural height of the visualizer. This is used to calculate
 * the height needed within the instrument view.
 *
 * Returns: A #gdouble.
 * Side effects: None.
 */
gdouble
ppg_visualizer_get_natural_height (PpgVisualizer *visualizer)
{
	g_return_val_if_fail(PPG_IS_VISUALIZER(visualizer), 0.0);
	return visualizer->priv->natural_height;
}