static void mex_grilo_feed_open_default (MexGriloProgram *program, MexGriloFeed *feed) { MexPlayer *player = mex_player_get_default (); mex_content_view_set_context (MEX_CONTENT_VIEW (player), MEX_MODEL (feed)); mex_content_view_set_content (MEX_CONTENT_VIEW (player), MEX_CONTENT (program)); }
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 void mex_content_box_toggle_open (MexContentBox *box) { MexContentBoxPrivate *priv = box->priv; gboolean close_notified, next_is_open; const gchar *mimetype; /* search history items should not appear in the "open" state */ mimetype = mex_content_get_metadata (priv->content, MEX_CONTENT_METADATA_MIMETYPE); if (!g_strcmp0 (mimetype, "x-mex/search")) return; /* if the close animation was cancelled then no notify for the closed state * will have been sent, therefore notify for the opened state does not need * to be emitted */ close_notified = (!priv->is_open && !clutter_timeline_is_playing (priv->timeline)); next_is_open = !priv->is_open; if (next_is_open) { /* opening */ clutter_timeline_set_direction (priv->timeline, CLUTTER_TIMELINE_FORWARD); mx_stylable_set_style_class (MX_STYLABLE (box), "open"); /* refresh the action list */ mex_content_view_set_content (MEX_CONTENT_VIEW (priv->action_list), priv->content); priv->extras_visible = TRUE; if (close_notified) g_object_notify_by_pspec (G_OBJECT (box), properties[PROP_OPEN]); mex_push_focus (MX_FOCUSABLE (priv->action_list)); } else { priv->is_closing = TRUE; /* closing */ mex_push_focus (MX_FOCUSABLE (priv->tile)); clutter_timeline_set_direction (priv->timeline, CLUTTER_TIMELINE_BACKWARD); priv->is_closing = FALSE; priv->extras_visible = TRUE; } if (!clutter_timeline_is_playing (priv->timeline)) clutter_timeline_rewind (priv->timeline); clutter_timeline_start (priv->timeline); priv->is_open = next_is_open; }
int main (int argc, char **argv) { const ClutterColor grey = { 0x40, 0x40, 0x40, 0xff }; ClutterActor *stage, *info_panel, *align; MxApplication *app; MxWindow *window; MexFeed *feed; MexProgram *program; mex_init (&argc, &argv); app = mx_application_new (&argc, &argv, "mex-info-panel-test", 0); mex_style_load_default (); window = mx_application_create_window (app); stage = (ClutterActor *) mx_window_get_clutter_stage (window); clutter_stage_set_color ((ClutterStage *) stage, &grey); align = g_object_new (MX_TYPE_FRAME, "x-align", MX_ALIGN_MIDDLE, "y-align", MX_ALIGN_END, NULL); mx_window_set_child (window, align); info_panel = mex_info_panel_new (MEX_INFO_PANEL_MODE_FULL); mx_bin_set_child (MX_BIN (align), info_panel); mx_window_set_has_toolbar (window, FALSE); clutter_actor_set_size (stage, 1024, 768); feed = mex_feed_new ("source", "title"); program = mex_program_new (feed); mex_content_set_metadata (MEX_CONTENT (program), MEX_CONTENT_METADATA_MIMETYPE, "video/mp4"); mex_content_set_metadata (MEX_CONTENT (program), MEX_CONTENT_METADATA_TITLE, "The cats on the moon"); mex_content_set_metadata (MEX_CONTENT (program), MEX_CONTENT_METADATA_SYNOPSIS, "An original title where cats are sent to the moon to catch all the mice which are naturally attracted there due to the large consistency of cheese, this results in a space race between NASA and CATSA, leading to war on the moon over territory claimed by cats"); mex_content_set_metadata (MEX_CONTENT (program), MEX_CONTENT_METADATA_STILL, "http://farm5.static.flickr.com/4013/4305303148_5cbc986a44_m.jpg"); mex_content_view_set_content (MEX_CONTENT_VIEW (info_panel), MEX_CONTENT (program)); clutter_actor_show (stage); clutter_main (); return 0; }
static void mex_content_box_set_content (MexContentView *view, MexContent *content) { MexContentBox *box = MEX_CONTENT_BOX (view); MexContentBoxPrivate *priv = box->priv; if (priv->content) g_object_unref (priv->content); priv->content = g_object_ref (content); mex_content_view_set_content (MEX_CONTENT_VIEW (priv->tile), content); mex_content_view_set_content (MEX_CONTENT_VIEW (priv->info_panel), content); /* setting the content on action_list is delayed until the box is opened to * ensure any additional actions registered after set_content is called are * available */ }
static void mex_content_box_set_context (MexContentView *view, MexModel *context) { MexContentBox *box = MEX_CONTENT_BOX (view); MexContentBoxPrivate *priv = box->priv; if (priv->context == context) return; if (priv->context) g_object_unref (priv->context); priv->context = g_object_ref (context); mex_content_view_set_context (MEX_CONTENT_VIEW (priv->action_list), context); mex_content_view_set_context (MEX_CONTENT_VIEW (priv->tile), context); mex_content_view_set_context (MEX_CONTENT_VIEW (priv->info_panel), context); }
static void mex_music_player_item_clicked (MxButton *button, MexMusicPlayer *player) { MexContent *content; content = g_object_get_data (G_OBJECT (button), "content"); mex_music_player_set_content (MEX_CONTENT_VIEW (player), content); mex_music_player_play (player); }
static void mex_media_controls_replace_content (MexMediaControls *self, MexContent *content) { MexPlayer *player; MxScrollable *related_box; MxAdjustment *adjustment; gdouble upper; MexMediaControlsPrivate *priv = self->priv; if (priv->content == content) return; player = mex_player_get_default (); mex_content_view_set_content (MEX_CONTENT_VIEW (player), content); if (priv->content) g_object_unref (priv->content); priv->content = g_object_ref_sink (content); mex_media_controls_update_header (self); mex_content_view_set_content (MEX_CONTENT_VIEW (priv->queue_button), content); mex_push_focus ((MxFocusable*) clutter_script_get_object (priv->script, "play-pause-button")); related_box = (MxScrollable *)clutter_script_get_object (priv->script, "related-box"); mx_scrollable_get_adjustments (MX_SCROLLABLE (related_box), &adjustment, NULL); mx_adjustment_get_values (adjustment, NULL, NULL, &upper, NULL, NULL, NULL); mx_adjustment_set_value (adjustment, upper); mx_scrollable_set_adjustments (MX_SCROLLABLE (related_box), adjustment, NULL); }
static gboolean button_release_event_cb (ClutterActor *actor, ClutterButtonEvent *event, gpointer user_data) { MexMediaControls *self = MEX_MEDIA_CONTROLS (user_data); MexContent *content = mex_content_view_get_content (MEX_CONTENT_VIEW (actor)); mex_media_controls_replace_content (self, content); return TRUE; }
/** * mex_column_add_content: * * Add an item to the column for the specified content at the specified * position. */ static void mex_column_add_content (MexColumn *column, MexContent *content, guint position) { MexColumnPrivate *priv = column->priv; ClutterActor *box; MexShadow *shadow; ClutterColor shadow_color = { 0, 0, 0, 128 }; GList *sibling; box = mex_content_box_new (); mex_content_view_set_content (MEX_CONTENT_VIEW (box), content); mex_content_view_set_context (MEX_CONTENT_VIEW (box), priv->model); sibling = g_list_nth (priv->children, position); priv->children = g_list_insert_before (priv->children, sibling, box); priv->n_items ++; /* add shadow */ shadow = mex_shadow_new (); mex_shadow_set_paint_flags (shadow, MEX_TEXTURE_FRAME_TOP | MEX_TEXTURE_FRAME_BOTTOM); mex_shadow_set_radius_y (shadow, 25); mex_shadow_set_color (shadow, &shadow_color); clutter_actor_add_effect_with_name (CLUTTER_ACTOR (box), "shadow", CLUTTER_EFFECT (shadow)); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (shadow), FALSE); g_signal_connect (box, "notify::open", G_CALLBACK (content_box_open_notify), column); /* set important if the column has focus */ mex_content_box_set_important (MEX_CONTENT_BOX (box), priv->has_focus); clutter_actor_set_parent (box, CLUTTER_ACTOR (column)); }
static void media_eos_cb (ClutterMedia *media, MexPlayer *player) { MexPlayerPrivate *priv = player->priv; priv->position = 0.0; if (priv->idle_mode) { /* loop the video in idle mode */ clutter_media_set_progress (media, priv->position); clutter_media_set_playing (media, TRUE); } else { /* Check to see if we have enqueued content and if so play it next */ MexContent *enqueued_content; enqueued_content = mex_media_controls_get_enqueued (MEX_MEDIA_CONTROLS (priv->controls), priv->content); /* set the control visible */ clutter_actor_animate (priv->info_panel, CLUTTER_EASE_IN_SINE, 250, "opacity", 0x00, NULL); mex_player_set_controls_visible (player, TRUE); if (enqueued_content) { priv->playing_from_queue = TRUE; mex_player_set_content (MEX_CONTENT_VIEW (player), enqueued_content); } else { priv->playing_from_queue = TRUE; mex_screensaver_uninhibit (priv->screensaver); clutter_media_set_progress (media, priv->position); clutter_media_set_playing (media, FALSE); priv->current_position = 0.0; priv->at_eos = TRUE; } /* focus the related content */ mex_media_controls_focus_content (MEX_MEDIA_CONTROLS (priv->controls), priv->content); } }
static void mex_queue_button_dispose (GObject *object) { MexQueueButton *q_button = MEX_QUEUE_BUTTON (object); /* Free-up resources and drop callback */ mex_queue_button_set_content (MEX_CONTENT_VIEW (q_button), NULL); if (q_button->priv->queue_model) { g_object_unref (q_button->priv->queue_model); q_button->priv->queue_model = NULL; } G_OBJECT_CLASS (mex_queue_button_parent_class)->dispose (object); }
static void mex_content_box_set_context (MexContentView *view, MexModel *model) { MexContentBox *box = MEX_CONTENT_BOX (view); MexContentBoxPrivate *priv = box->priv; if (priv->model == model) return; if (priv->model) g_object_unref (priv->model); priv->model = g_object_ref (model); mex_content_view_set_context (MEX_CONTENT_VIEW (priv->action_list), model); }
static void mex_content_box_notify_open_cb (MexExpanderBox *box, GParamSpec *pspec) { GList *actions; ClutterStage *stage = CLUTTER_STAGE ( clutter_actor_get_stage (CLUTTER_ACTOR (box))); MxFocusManager *fmanager = mx_focus_manager_get_for_stage (stage); MexActionManager *manager = mex_action_manager_get_default (); MexContentBoxPrivate *priv = MEX_CONTENT_BOX (box)->priv; gboolean open = mex_expander_box_get_open (box); if (!open) { /* If the action list has focus, push it back onto the tile */ if (mex_actor_has_focus (fmanager, priv->action_list)) mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->tile)); return; } /* Refresh the info panel and the action list */ mex_content_view_set_content (MEX_CONTENT_VIEW (priv->panel), priv->content); mex_action_list_refresh (MEX_ACTION_LIST (priv->action_list)); /* See if we have any actions */ actions = mex_action_manager_get_actions_for_content (manager, priv->content); /* Push focus onto the action list if we have actions, otherwise onto * the tile. */ if (actions) { clutter_actor_show (priv->action_list); mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->action_list)); g_list_free (actions); } else { clutter_actor_hide (priv->action_list); mx_focus_manager_push_focus (fmanager, MX_FOCUSABLE (priv->tile)); } }
static gboolean key_press_event_cb (ClutterActor *actor, ClutterKeyEvent *event, gpointer user_data) { MexMediaControls *self = MEX_MEDIA_CONTROLS (user_data); if (MEX_KEY_OK (event->keyval)) { MexContent *content = mex_content_view_get_content (MEX_CONTENT_VIEW (actor)); mex_media_controls_replace_content (self, content); return TRUE; } return FALSE; }
static void mex_content_box_timeline_completed (ClutterTimeline *timeline, MexContentBox *box) { MexContentBoxPrivate *priv = box->priv; priv->extras_visible = (clutter_timeline_get_direction (timeline) == CLUTTER_TIMELINE_FORWARD); if (!priv->extras_visible) { /* box is now "closed" */ mx_stylable_set_style_class (MX_STYLABLE (box), ""); g_object_notify_by_pspec (G_OBJECT (box), properties[PROP_OPEN]); } if (!priv->is_open) mex_content_view_set_content (MEX_CONTENT_VIEW (priv->action_list), NULL); }
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_music_player_update_index (MexMusicPlayer *player, gint new_index) { MexMusicPlayerPrivate *priv = player->priv; gint content_index, length; MexContent *new_content; length = mex_model_get_length (priv->model); if (priv->repeat) { if (new_index >= length) new_index = 0; else if (new_index < 0) new_index = length - 1; } else { if (new_index >= length) new_index = length - 1; else if (new_index < 0) new_index = 0; } priv->current_index = new_index; if (priv->shuffle) content_index = g_array_index (priv->shuffle, gint, priv->current_index); else content_index = priv->current_index; new_content = mex_model_get_content (priv->model, content_index); mex_music_player_set_content (MEX_CONTENT_VIEW (player), new_content); }
static void mex_content_box_set_content (MexContentView *view, MexContent *content) { MexContentBox *box = (MexContentBox *) view; MexContentBoxPrivate *priv; priv = box->priv; if (priv->content == content) return; mex_content_view_set_content (MEX_CONTENT_VIEW (priv->tile), content); mex_content_view_set_content (MEX_CONTENT_VIEW (priv->action_list), content); if (priv->content) { GList *l; for (l = priv->bindings; l; l = l->next) g_object_unref (l->data); g_list_free (priv->bindings); priv->bindings = NULL; g_object_unref (priv->content); priv->content = NULL; } if (content) { int i; priv->content = g_object_ref_sink (content); for (i = 0; content_bindings[i].id != MEX_CONTENT_METADATA_NONE; i++) { const gchar *property; GBinding *binding; property = mex_content_get_property_name (content, content_bindings[i].id); if (property == NULL) { /* The Content does not provide a GObject property for this * kind of metadata, we can only sync at creation time */ const gchar *metadata; metadata = mex_content_get_metadata (content, content_bindings[i].id); g_object_set (box, content_bindings[i].target, metadata, NULL); continue; } if (content_bindings[i].fallback) binding = g_object_bind_property_full (content, property, box, content_bindings[i].target, G_BINDING_SYNC_CREATE, content_bindings[i].fallback, NULL, content, NULL); else binding = g_object_bind_property (content, property, box, content_bindings[i].target, G_BINDING_SYNC_CREATE); priv->bindings = g_list_prepend (priv->bindings, binding); } } }
static gboolean mex_player_key_press_event (ClutterActor *actor, ClutterKeyEvent *event) { MexPlayerPrivate *priv = MEX_PLAYER (actor)->priv; ClutterStage *stage; MxFocusManager *fmanager; stage = (ClutterStage*) clutter_actor_get_stage (actor); fmanager = mx_focus_manager_get_for_stage (stage); switch (event->keyval) { case CLUTTER_KEY_Down: { if (!priv->controls_visible && !priv->info_visible) return mex_player_set_controls_visible (MEX_PLAYER (actor), TRUE); break; } case MEX_KEY_INFO: { MexContent *content; content = priv->content; if (priv->info_visible) { /* hide the info panel */ clutter_actor_animate (priv->info_panel, CLUTTER_EASE_IN_SINE, 250, "opacity", 0x00, NULL); mx_widget_set_disabled (MX_WIDGET (priv->info_panel), TRUE); mx_widget_set_disabled (MX_WIDGET (priv->controls), FALSE); priv->info_visible = FALSE; if (priv->controls_prev_visible) mex_player_set_controls_visible (MEX_PLAYER (actor), TRUE); } else { /* if you're pressing info button while the media controls are up set them as previously visible */ if (priv->controls_visible) priv->controls_prev_visible = TRUE; MxFocusable *focusable; focusable = mx_focus_manager_get_focused (fmanager); if (MEX_IS_CONTENT_TILE (focusable) && priv->controls_prev_visible == TRUE) { content = mex_content_view_get_content (MEX_CONTENT_VIEW (focusable)); /* to avoid any accidental leak */ if (priv->related_tile) { g_object_unref (priv->related_tile); priv->related_tile = NULL; } priv->related_tile = g_object_ref (focusable); } mex_content_view_set_content (MEX_CONTENT_VIEW (priv->info_panel), content); /* show the info panel */ clutter_actor_animate (priv->info_panel, CLUTTER_EASE_IN_SINE, 250, "opacity", 0xff, NULL); mx_widget_set_disabled (MX_WIDGET (priv->info_panel), FALSE); mx_widget_set_disabled (MX_WIDGET (priv->controls), TRUE); priv->info_visible = TRUE; mex_player_set_controls_visible (MEX_PLAYER (actor), FALSE); mex_push_focus (MX_FOCUSABLE (priv->info_panel)); } return TRUE; } } return FALSE; }
void mex_media_controls_set_content (MexMediaControls *self, MexContent *content, MexModel *context) { MexMediaControlsPrivate *priv = self->priv; gboolean show_description; g_return_if_fail (MEX_IS_CONTENT (content)); if (priv->model == context) { if (priv->content == content) return; if (priv->content) g_object_unref (priv->content); if (content) priv->content = g_object_ref_sink (content); mex_media_controls_focus_content (self, priv->content); mex_media_controls_update_header (self); return; } if (priv->model) { g_object_unref (priv->model); priv->model = NULL; } if (context) priv->model = g_object_ref_sink (context); if (priv->content) { g_object_unref (priv->content); priv->content = NULL; } if (content) priv->content = g_object_ref_sink (content); priv->is_queue_model = FALSE; mex_media_controls_update_header (self); /* We may not have a context if we're launched by something like SetUri*/ if (context) { MexModel *orig_model; orig_model = mex_model_get_model (context); g_object_set (G_OBJECT (priv->proxy_model), "model", orig_model, NULL); mex_view_model_set_start_content (priv->proxy_model, priv->content); mex_view_model_set_loop (priv->proxy_model, TRUE); /* Work out if the context was a queue FIXME unreliable */ /* From coloumn context = MexViewModel MexAggregateModel MexQueueModel */ /* From grid context = MexProxyModel MexProxyModel MexQueueModel */ if (MEX_IS_PROXY_MODEL (context)) { MexModel *model_from_proxy; model_from_proxy = mex_proxy_model_get_model (MEX_PROXY_MODEL (orig_model)); if (MEX_IS_QUEUE_MODEL (model_from_proxy)) priv->is_queue_model = TRUE; } else if (MEX_IS_AGGREGATE_MODEL (orig_model)) { MexModel *real_model; real_model = mex_aggregate_model_get_model_for_content (MEX_AGGREGATE_MODEL (orig_model), content); if (MEX_IS_QUEUE_MODEL (real_model)) priv->is_queue_model = TRUE; } } /* Update content on the queue button */ mex_content_view_set_content (MEX_CONTENT_VIEW (priv->queue_button), priv->content); /* show the description rather than the seek bar for certain content */ show_description = !g_strcmp0 ("x-mex/tv", mex_content_get_metadata (priv->content, MEX_CONTENT_METADATA_MIMETYPE)); mex_media_controls_show_description(self, show_description); }