ClutterActor * mex_telepathy_channel_create_static_image (void) { ClutterActor *actor; gchar *static_image_path; GError *error = NULL; static_image_path = g_build_filename (mex_get_data_dir (), "style", "thumb-call-pip-off.png", NULL); actor = clutter_texture_new_from_file (static_image_path, &error); if (error) { g_warning ("Error loading texture %s", error->message); g_clear_error (&error); } if (static_image_path) g_free (static_image_path); clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (actor), TRUE); return actor; }
/* * If we need to, generate a thumbnail. * * If the URL is not file:/// then we assume it's okay to use. * */ static void mex_grilo_program_thumbnail (MexContent *content, GrlMedia *media) { const char *url; char *thumb_path; /* If the media isn't local, then we'll ignore it for now */ url = grl_media_get_url (media); if (url == NULL || !g_str_has_prefix (url, "file:///")) return; if (GRL_IS_MEDIA_BOX (media)) { gchar *tmp; tmp = g_build_filename (mex_get_data_dir (), "common", "folder-tile.png", NULL); mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, tmp); g_free (tmp); return; } /* * If we're already got a thumbnail, see if we're happy with it or want to * ignore it. */ thumb_path = (char*)mex_content_get_metadata (content, MEX_CONTENT_METADATA_STILL); if (thumb_path) { /* If the thumbnail is already a good one, we're done */ if (thumb_path && strstr (thumb_path, "/.thumbnails/x-huge/")) return; /* * If the thumbnail currently set is a "normal" thumbnail we ignore it on the * basis that it's likely to have been generated by Totem, and thus is bad. * If your platform doesn't have Totem then this can be removed! */ if (thumb_path && strstr (thumb_path, "/.thumbnails/normal/")) mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, NULL); } /* * Now see if we've a thumbnail generated already. TODO: use the Tumbler API * to do this. */ thumb_path = get_thumbnail_path_for_uri (url); if (g_file_test (thumb_path, G_FILE_TEST_EXISTS)) { gchar *thumb_uri = g_filename_to_uri (thumb_path, NULL, NULL); mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, thumb_uri); g_free (thumb_uri); } else { mex_thumbnailer_generate (url, grl_media_get_mime (media), thumbnail_cb, content); } g_free (thumb_path); }
static void mex_info_bar_init (MexInfoBar *self) { ClutterScript *script; ClutterActor *notification_area; GError *err = NULL; gchar *tmp; MexInfoBarPrivate *priv = self->priv = INFO_BAR_PRIVATE (self); priv->script = script = clutter_script_new (); tmp = g_build_filename (mex_get_data_dir (), "json", "info-bar.json", NULL); clutter_script_load_from_file (script, tmp, &err); g_free (tmp); if (err) g_error ("Could not load info bar: %s", err->message); priv->group = CLUTTER_ACTOR (clutter_script_get_object (script, "main-group")); clutter_actor_set_parent (priv->group, CLUTTER_ACTOR (self)); priv->settings_button = CLUTTER_ACTOR (clutter_script_get_object (script, "settings-button")); priv->power_button = CLUTTER_ACTOR (clutter_script_get_object (script, "power-button")); priv->back_button = CLUTTER_ACTOR (clutter_script_get_object (script, "back-button")); priv->notification_source = mex_generic_notification_source_new (); notification_area = CLUTTER_ACTOR (clutter_script_get_object (priv->script, "notification-area")); mex_notification_area_add_source (MEX_NOTIFICATION_AREA (notification_area), MEX_NOTIFICATION_SOURCE (priv->notification_source)); g_signal_connect (priv->settings_button, "clicked", G_CALLBACK (_show_settings_dialog_cb), self); g_signal_connect (priv->power_button, "clicked", G_CALLBACK (_show_power_dialog_cb), self); g_signal_connect (priv->back_button, "clicked", G_CALLBACK (_back_button_cb), self); _create_power_dialog (MEX_INFO_BAR (self)); _create_settings_dialog (MEX_INFO_BAR (self)); }
void mex_player_set_idle_mode (MexPlayer *player, gboolean idle) { MexPlayerPrivate *priv = player->priv; if (priv->idle_mode == idle) return; priv->idle_mode = idle; mex_player_set_controls_visible (player, !idle); if (idle) { gchar *tmp; clutter_actor_hide (priv->controls); clutter_actor_hide (priv->info_panel); mx_widget_set_disabled (MX_WIDGET (player), TRUE); clutter_actor_set_reactive (CLUTTER_ACTOR (player), FALSE); if (priv->content) { save_old_content (player); g_object_unref (priv->content); priv->content = NULL; } tmp = g_strconcat ("file://", mex_get_data_dir (), "/common/style/background-loop.mkv", NULL); clutter_media_set_uri (priv->media, tmp); g_free (tmp); clutter_media_set_playing (priv->media, TRUE); /* we're idle so we don't mind the screensaver coming on */ mex_screensaver_uninhibit (priv->screensaver); } else { clutter_actor_show (priv->controls); clutter_actor_show (priv->info_panel); mx_widget_set_disabled (MX_WIDGET (player), FALSE); clutter_actor_set_reactive (CLUTTER_ACTOR (player), TRUE); clutter_media_set_playing (priv->media, FALSE); clutter_media_set_uri (priv->media, NULL); /* we're playing real content so don't allow the screensaver */ mex_screensaver_inhibit (priv->screensaver); } }
static struct lirc_config * mex_lirc_init (const gchar *name) { int lirc_fd, res; gchar *tmp; lirc_fd = lirc_init ((char *)name, 1); if (lirc_fd == -1) g_warning (G_STRLOC ": LIRC initialisation failed"); else { struct lirc_config *config = NULL; /* Load the default config */ tmp = g_build_filename (mex_get_data_dir (), "mex-lircrc", NULL); res = lirc_readconfig (tmp, &config, NULL); g_free (tmp); if (res == 0) { int flags; GIOChannel *channel; /* Set non-blocking flag */ flags = fcntl (lirc_fd, F_GETFL); fcntl (lirc_fd, F_SETFL, flags | O_NONBLOCK); /* Create IOChannel to do non-blocking reads */ channel = g_io_channel_unix_new (lirc_fd); g_io_add_watch (channel, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_NVAL | G_IO_HUP, (GIOFunc)mex_lirc_read_cb, config); return config; } else { g_warning (G_STRLOC ": Error reading LIRC config"); lirc_deinit (); } } return NULL; }
static void mex_telepathy_channel_create_toolbar (MexTelepathyChannel *self) { MexTelepathyChannelPrivate *priv = MEX_TELEPATHY_CHANNEL (self)->priv; gchar *static_image_path; ClutterActor *toolbar; MxAction *end_action; MxAction *camera_action; MxAction *mute_action; GError *error = NULL; // Create the user label priv->avatar_image = mx_image_new (); static_image_path = g_build_filename (mex_get_data_dir (), "style", "thumb-call-avatar-small.png", NULL); mx_image_set_from_file (MX_IMAGE (priv->avatar_image), static_image_path, &error); if (error) { g_warning ("Error loading texture %s", error->message); g_clear_error (&error); } if (static_image_path) g_free (static_image_path); priv->title_label = mx_label_new (); mx_label_set_y_align (MX_LABEL (priv->title_label), MX_ALIGN_MIDDLE); mx_label_set_x_align (MX_LABEL (priv->title_label), MX_ALIGN_MIDDLE); end_action = mx_action_new_full ("End", "Hang Up", G_CALLBACK (mex_telepathy_channel_on_hangup), self); priv->end_button = mex_action_button_new (end_action); mx_stylable_set_style_class (MX_STYLABLE (priv->end_button), "EndCall"); camera_action = mx_action_new_full("Camera", "Camera Off", G_CALLBACK (mex_telepathy_channel_toggle_camera), self); priv->camera_button = mex_action_button_new (camera_action); /* off by default */ mex_telepathy_channel_set_camera_state (self, FALSE); mute_action = mx_action_new_full("Mute", "Mic Off", G_CALLBACK (mex_telepathy_channel_toggle_mute), self); priv->mute_button = mex_action_button_new (mute_action); mx_stylable_set_style_class (MX_STYLABLE (priv->mute_button), "MediaMute"); toolbar = mx_box_layout_new (); clutter_actor_set_width (toolbar, 980); clutter_actor_set_height (toolbar, 48); mx_stylable_set_style_class (MX_STYLABLE (toolbar), "MexCallControlsTitle"); // Put the buttons in the toolbar mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar), priv->avatar_image, 0, "expand", FALSE, "x-align", MX_ALIGN_END, "x-fill", FALSE, NULL); mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar), priv->title_label, 1, "expand", TRUE, NULL); mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar), priv->camera_button, 2, "expand", TRUE, NULL); mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar), priv->mute_button, 3, "expand", TRUE, NULL); mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar), priv->end_button, 4, "expand", TRUE, NULL); priv->toolbar_area = mx_frame_new (); mx_bin_set_child (MX_BIN (priv->toolbar_area), toolbar); mx_stylable_set_style_class (MX_STYLABLE (priv->toolbar_area), "ToolbarArea"); }
static void mex_info_bar_init (MexInfoBar *self) { ClutterScript *script; ClutterActor *notification_area; GError *err = NULL; gchar *tmp; GSettings *settings; MexInfoBarPrivate *priv = self->priv = INFO_BAR_PRIVATE (self); priv->script = script = clutter_script_new (); tmp = g_build_filename (mex_get_data_dir (), "json", "info-bar.json", NULL); clutter_script_load_from_file (script, tmp, &err); g_free (tmp); if (err) g_error ("Could not load info bar: %s", err->message); priv->group = CLUTTER_ACTOR (clutter_script_get_object (script, "main-group")); clutter_actor_set_parent (priv->group, CLUTTER_ACTOR (self)); priv->settings_button = CLUTTER_ACTOR (clutter_script_get_object (script, "settings-button")); priv->power_button = CLUTTER_ACTOR (clutter_script_get_object (script, "power-button")); priv->back_button = CLUTTER_ACTOR (clutter_script_get_object (script, "back-button")); priv->notification_source = mex_generic_notification_source_new (); notification_area = CLUTTER_ACTOR (clutter_script_get_object (priv->script, "notification-area")); /* ensure the notification area is above any other actors */ clutter_actor_set_child_above_sibling (clutter_actor_get_parent (notification_area), notification_area, NULL); mex_notification_area_add_source (MEX_NOTIFICATION_AREA (notification_area), MEX_NOTIFICATION_SOURCE (priv->notification_source)); g_signal_connect (priv->settings_button, "clicked", G_CALLBACK (_show_settings_dialog_cb), self); g_signal_connect (priv->power_button, "clicked", G_CALLBACK (_close_request_cb), self); g_signal_connect (priv->back_button, "clicked", G_CALLBACK (_back_button_cb), self); _create_settings_dialog (MEX_INFO_BAR (self)); settings = g_settings_new ("org.media-explorer.Shell"); if (!g_settings_get_boolean (settings, "close-button-visible")) clutter_actor_hide (priv->power_button); g_clear_object (&settings); }
static gboolean _create_settings_dialog (MexInfoBar *self) { MexInfoBarPrivate *priv = self->priv; ClutterActor *dialog, *network_graphic; ClutterActor *network_tile, *dialog_layout, *dialog_label; ClutterActor *network_button; MxAction *close_dialog, *network_settings; dialog = mx_dialog_new (); mx_stylable_set_style_class (MX_STYLABLE (dialog), "MexInfoBarDialog"); dialog_label = mx_label_new_with_text (_("Settings")); mx_stylable_set_style_class (MX_STYLABLE (dialog_label), "DialogHeader"); /* Create actions for settings dialog */ network_settings = _action_new_from_desktop_file ("mex-networks.desktop"); close_dialog = mx_action_new_full ("close", _("Close"), G_CALLBACK (_close_dialog_cb), self); dialog_layout = mx_table_new (); mx_table_set_column_spacing (MX_TABLE (dialog_layout), 10); mx_table_set_row_spacing (MX_TABLE (dialog_layout), 30); mx_table_insert_actor (MX_TABLE (dialog_layout), CLUTTER_ACTOR (dialog_label), 0, 0); if (network_settings) { gchar *tmp; network_graphic = mx_image_new (); mx_stylable_set_style_class (MX_STYLABLE (network_graphic), "NetworkGraphic"); tmp = g_build_filename (mex_get_data_dir (), "style", "graphic-network.png", NULL); mx_image_set_from_file (MX_IMAGE (network_graphic), tmp, NULL); g_free (tmp); network_tile = mex_tile_new (); mex_tile_set_label (MEX_TILE (network_tile), _("Network")); mex_tile_set_important (MEX_TILE (network_tile), TRUE); network_button = mx_button_new (); mx_button_set_action (MX_BUTTON (network_button), network_settings); mx_bin_set_child (MX_BIN (network_tile), network_button); mx_bin_set_child (MX_BIN (network_button), network_graphic); mx_table_insert_actor (MX_TABLE (dialog_layout), CLUTTER_ACTOR (network_tile), 1, 1); } if (!network_settings) { ClutterActor *no_settings; no_settings = mx_label_new_with_text (_("No settings helpers installed")); clutter_actor_destroy (priv->settings_button); mx_table_insert_actor (MX_TABLE (dialog_layout), CLUTTER_ACTOR (no_settings), 1, 0); } mx_bin_set_child (MX_BIN (dialog), dialog_layout); mx_dialog_add_action (MX_DIALOG (dialog), close_dialog); priv->settings_dialog = g_object_ref (dialog); return TRUE; }
static void mex_media_controls_init (MexMediaControls *self) { ClutterActor *actor; ClutterScript *script; GError *err = NULL; MxAdjustment *adjustment; ClutterActor *related_box; gchar *tmp; MexMediaControlsPrivate *priv = self->priv = MEDIA_CONTROLS_PRIVATE (self); priv->script = script = clutter_script_new (); tmp = g_build_filename (mex_get_data_dir (), "json", "media-controls.json", NULL); clutter_script_load_from_file (script, tmp, &err); g_free (tmp); if (err) g_error ("Could not load media controls interface: %s", err->message); priv->vbox = (ClutterActor*) clutter_script_get_object (script, "media-controls"); clutter_actor_set_parent (priv->vbox, CLUTTER_ACTOR (self)); /* add shadow to media controls box */ actor = (ClutterActor *) clutter_script_get_object (script, "media-controls-box"); clutter_actor_add_effect (actor, CLUTTER_EFFECT (mex_shadow_new ())); /* vertical fade effect */ priv->vertical_effect = mx_fade_effect_new (); clutter_actor_add_effect (priv->vbox, priv->vertical_effect); mx_scrollable_get_adjustments (MX_SCROLLABLE (mx_bin_get_child (MX_BIN (priv->vbox))), NULL, &adjustment); g_signal_connect (adjustment, "changed", G_CALLBACK (notify_vertical_changed_cb), self); g_signal_connect (adjustment, "notify::value", G_CALLBACK (notify_vertical_value_cb), self); /* horizontal fade effect */ priv->horizontal_effect = mx_fade_effect_new (); related_box = (ClutterActor *) clutter_script_get_object (priv->script, "related-box"); clutter_actor_add_effect (related_box, priv->horizontal_effect); mx_scrollable_get_adjustments (MX_SCROLLABLE (related_box), &adjustment, NULL); g_signal_connect (adjustment, "changed", G_CALLBACK (notify_horizontal_changed_cb), self); g_signal_connect (adjustment, "notify::value", G_CALLBACK (notify_horizontal_value_cb), self); /* slider setup */ priv->slider = (ClutterActor*) clutter_script_get_object (script, "slider"); g_signal_connect (priv->slider, "notify::value", G_CALLBACK (slider_value_changed_cb), self); g_signal_connect (priv->slider, "captured-event", G_CALLBACK (slider_captured_event), self); priv->play_pause_action = (MxAction*) clutter_script_get_object (script, "play-pause-action"); priv->stop_action = (MxAction*) clutter_script_get_object (script, "stop-action"); priv->add_to_queue_action = (MxAction*) clutter_script_get_object (script, "add-to-queue-action"); priv->queue_button = (ClutterActor *) clutter_script_get_object (script, "add-to-queue-button"); g_signal_connect (priv->play_pause_action, "activated", G_CALLBACK (mex_media_controls_play_cb), self); g_signal_connect (priv->stop_action, "activated", G_CALLBACK (mex_media_controls_stop_cb), self); #if 0 g_signal_connect (priv->add_to_queue_action, "activated", G_CALLBACK (mex_media_controls_add_to_queue_cb), self); #endif /* proxy setup */ priv->proxy_model = MEX_VIEW_MODEL (mex_view_model_new (NULL)); /* FIXME: Set an arbitrary 200-item limit as we can't handle large * amounts of actors without massive slow-down. */ mex_view_model_set_limit (priv->proxy_model, 200); priv->proxy = mex_content_proxy_new (MEX_MODEL (priv->proxy_model), CLUTTER_CONTAINER (related_box), MEX_TYPE_CONTENT_TILE); g_signal_connect (priv->proxy, "object-created", G_CALLBACK (tile_created_cb), self); priv->is_disabled = TRUE; }
static void _reset_thumbnail (MexContentTile *tile) { MexContentTilePrivate *priv = tile->priv; MexDownloadQueue *queue = mex_download_queue_get_default (); const gchar *mime = NULL; gchar *placeholder_filename = NULL; queue = mex_download_queue_get_default (); /* cancel any download already in progress */ if (priv->download_id) { mex_download_queue_cancel (queue, priv->download_id); priv->download_id = NULL; } priv->thumbnail_loaded = FALSE; /* Load placeholder image */ if (priv->content) mime = mex_content_get_metadata (priv->content, MEX_CONTENT_METADATA_MIMETYPE); if (mime && g_str_has_prefix (mime, "image/")) { placeholder_filename = "thumb-image.png"; } else if (mime && g_str_equal (mime, "x-mex/tv")) { placeholder_filename = "thumb-tv.png"; } else if (mime && g_str_equal (mime, "video/dvd")) { placeholder_filename = "thumb-disc.png"; } else if (mime && (g_str_has_prefix (mime, "video/") || g_str_equal (mime, "x-mex/media"))) { placeholder_filename = "thumb-video.png"; } else if (mime && (g_str_has_prefix (mime, "audio/"))) { placeholder_filename = "thumb-music.png"; } else if (mime && g_str_equal (mime, "x-grl/box")) { placeholder_filename = "folder-tile.png"; } else if (mime && g_str_equal (mime, "x-mex/group")) { placeholder_filename = "folder-tile.png"; } else if (mime && g_str_equal (mime, "x-mex/app")) { placeholder_filename = "thumb-app.png"; } if (placeholder_filename) { gchar *tmp; const gchar *dir = mex_get_data_dir (); tmp = g_build_filename (dir, "style", placeholder_filename, NULL); _update_thumbnail_from_image (tile, tmp); g_free (tmp); } else { mx_image_clear (MX_IMAGE (priv->image)); /* Reset the height - really, we ought to reset the width and height, * but for all our use-cases, we want to keep the set width. */ clutter_actor_set_height (priv->image, -1); priv->image_set = FALSE; return; } clutter_actor_set_size (priv->image, priv->thumb_width, priv->thumb_height); }