static void mex_content_tile_paint (ClutterActor *actor) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (actor)->priv; if (priv->content && MEX_IS_PROGRAM (priv->content)) _mex_program_complete (MEX_PROGRAM (priv->content)); if (!priv->thumbnail_loaded && !priv->download_id) _update_thumbnail (MEX_CONTENT_TILE (actor)); CLUTTER_ACTOR_CLASS (mex_content_tile_parent_class)->paint (actor); }
static gboolean _stop_video_preview (MexContentTile *self) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (self)->priv; if (priv->start_video_preview > 0) g_source_remove (priv->start_video_preview); /* video never started */ if (priv->child == priv->image) return FALSE; if (!priv->video_preview) return FALSE; clutter_media_set_playing (CLUTTER_MEDIA (priv->video_preview), FALSE); clutter_actor_remove_child (CLUTTER_ACTOR (self), priv->video_preview); clutter_actor_add_child (CLUTTER_ACTOR (self), priv->image); /* After setting the child the old child is killed off so NULL this to * help with checks */ priv->video_preview = NULL; return FALSE; }
static void mex_content_tile_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (object)->priv; switch (property_id) { case PROP_THUMB_WIDTH: priv->thumb_width = g_value_get_int (value); /* Ideally we'd use the image_set variable to determine if we set this, * but for all our use-cases, we always want the set thumbnail width. */ clutter_actor_set_width (priv->image, priv->thumb_width); break; case PROP_THUMB_HEIGHT: priv->thumb_height = g_value_get_int (value); if (priv->image_set) clutter_actor_set_height (priv->image, priv->thumb_height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } }
static MxFocusable* mex_content_tile_accept_focus (MxFocusable *focusable, MxFocusHint hint) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (focusable)->priv; clutter_actor_grab_key_focus (CLUTTER_ACTOR (focusable)); priv->start_video_preview = g_timeout_add_seconds (1, (GSourceFunc)_start_video_preview, MEX_CONTENT_TILE (focusable)); g_signal_emit (focusable, signals[FOCUS_IN], 0); return focusable; }
static void mex_content_tile_dispose (GObject *object) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (object)->priv; if (priv->content) { /* remove the reference to the MexContent and also disconnect the signal * handlers */ mex_content_tile_set_content (MEX_CONTENT_VIEW (object), NULL); } if (priv->model) { g_object_unref (priv->model); priv->model = NULL; } if (priv->download_id) { MexDownloadQueue *dl_queue = mex_download_queue_get_default (); mex_download_queue_cancel (dl_queue, priv->download_id); priv->download_id = NULL; } G_OBJECT_CLASS (mex_content_tile_parent_class)->dispose (object); }
static MexModel* mex_content_tile_get_context (MexContentView *view) { MexContentTile *tile = MEX_CONTENT_TILE (view); MexContentTilePrivate *priv = tile->priv; return priv->model; }
static void mex_content_tile_set_content (MexContentView *view, MexContent *content) { MexContentTile *tile = MEX_CONTENT_TILE (view); MexContentTilePrivate *priv = tile->priv; const gchar *label_prop_name, *secondary_label_prop_name; if (priv->content == content) return; if (priv->changed_id) { g_signal_handler_disconnect (priv->content, priv->changed_id); priv->changed_id = 0; } if (priv->content) { g_object_unref (priv->content); priv->content = NULL; } if (!content) return; priv->content = g_object_ref_sink (content); /* Update title/thumbnail display */ label_prop_name = mex_content_get_property_name (priv->content, MEX_CONTENT_METADATA_TITLE); secondary_label_prop_name = mex_content_get_property_name (priv->content, MEX_CONTENT_METADATA_ARTIST); g_object_bind_property (content, label_prop_name, tile, "label", G_BINDING_SYNC_CREATE); if (secondary_label_prop_name) { g_object_bind_property (content, secondary_label_prop_name, tile, "secondary-label", G_BINDING_SYNC_CREATE); } _update_logo (tile); _reset_thumbnail (tile); /* TODO: use g_object_bind_property */ priv->changed_id = g_signal_connect (priv->content, "notify", G_CALLBACK (_content_notify), view); }
static void mex_content_tile_actor_removed (ClutterActor *container, ClutterActor *actor) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (container)->priv; if (priv->child == actor) priv->child = NULL; }
static MxFocusable* mex_content_tile_move_focus (MxFocusable *focusable, MxFocusDirection direction, MxFocusable *old_focus) { g_signal_emit (focusable, signals[FOCUS_OUT], 0); _stop_video_preview (MEX_CONTENT_TILE (old_focus)); return NULL; }
static void mex_content_tile_set_context (MexContentView *view, MexModel *model) { MexContentTile *tile = MEX_CONTENT_TILE (view); MexContentTilePrivate *priv = tile->priv; if (priv->model) g_object_unref (priv->model); priv->model = g_object_ref (model); }
static void mex_content_tile_actor_added (ClutterActor *container, ClutterActor *actor) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (container)->priv; if (MX_IS_TOOLTIP (actor)) return; if (priv->child) clutter_actor_remove_child (container, priv->child); priv->child = actor; }
static void download_queue_completed (MexDownloadQueue *queue, const gchar *uri, const gchar *buffer, gsize count, const GError *error, gpointer user_data) { MexContentTile *tile = MEX_CONTENT_TILE (user_data); MexContentTilePrivate *priv = tile->priv; GError *suberror = NULL; priv->download_id = NULL; priv->thumbnail_loaded = TRUE; if (error) { g_warning ("Error loading %s: %s", uri, error->message); return; } /* TODO: Find a way of not having to do a g_memdup here */ if (!mx_image_set_from_buffer_at_size (MX_IMAGE (priv->image), g_memdup (buffer, count), count, (GDestroyNotify)g_free, priv->thumb_width, priv->thumb_height, &suberror)) { g_warning ("Error loading %s: %s", uri, suberror->message); g_error_free (suberror); /* TODO: Maybe set a broken-image tile? */ return; } priv->image_set = TRUE; clutter_actor_set_size (priv->image, priv->thumb_width, priv->thumb_height); }
static void mex_content_tile_dispose (GObject *object) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (object)->priv; if (priv->content) { /* remove the reference to the MexContent and also disconnect the signal * handlers */ mex_content_tile_set_content (MEX_CONTENT_VIEW (object), NULL); } if (priv->model) { g_object_unref (priv->model); priv->model = NULL; } if (priv->download_id) { MexDownloadQueue *dl_queue = mex_download_queue_get_default (); mex_download_queue_cancel (dl_queue, priv->download_id); priv->download_id = NULL; } if (priv->start_video_preview > 0) g_source_remove (priv->start_video_preview); if (priv->stop_video_preview > 0) g_source_remove (priv->stop_video_preview); /* This may or may not be parented so explicitly mark for destroying */ if (priv->video_preview) { clutter_actor_destroy (CLUTTER_ACTOR (priv->video_preview)); priv->video_preview = NULL; } G_OBJECT_CLASS (mex_content_tile_parent_class)->dispose (object); }
static void mex_content_tile_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { MexContentTilePrivate *priv = MEX_CONTENT_TILE (object)->priv; switch (property_id) { case PROP_THUMB_WIDTH: g_value_set_int (value, priv->thumb_width); break; case PROP_THUMB_HEIGHT: g_value_set_int (value, priv->thumb_height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } }
static void mex_content_tile_set_content (MexContentView *view, MexContent *content) { MexContentTile *tile = MEX_CONTENT_TILE (view); MexContentTilePrivate *priv = tile->priv; if (priv->content == content) return; if (priv->changed_id) { g_signal_handler_disconnect (priv->content, priv->changed_id); priv->changed_id = 0; } if (priv->content) { g_object_unref (priv->content); priv->content = NULL; } if (!content) return; priv->content = g_object_ref_sink (content); /* Update title/thumbnail display */ _update_title (tile); _update_logo (tile); _reset_thumbnail (tile); /* TODO: use g_object_bind_property */ priv->changed_id = g_signal_connect (priv->content, "notify", G_CALLBACK (_content_notify), view); }