1 /*
2 * Photos - access, organize and share your photos on GNOME
3 * Copyright © 2013 Intel Corporation. All rights reserved.
4 * Copyright © 2013 – 2019 Red Hat, Inc.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "config.h"
22
23 #include "photos-dlna-renderers-dialog.h"
24
25 #include <gio/gio.h>
26 #include <glib.h>
27 #include <glib/gi18n.h>
28
29 #include "photos-base-manager.h"
30 #include "photos-dlna-renderer.h"
31 #include "photos-dlna-renderers-manager.h"
32 #include "photos-item-manager.h"
33 #include "photos-local-item.h"
34 #include "photos-remote-display-manager.h"
35 #include "photos-search-context.h"
36 #include "photos-utils.h"
37
38
39 struct _PhotosDlnaRenderersDialog
40 {
41 GtkDialog parent_instance;
42 PhotosBaseManager *item_mngr;
43 PhotosDlnaRenderersManager *renderers_mngr;
44 PhotosRemoteDisplayManager *remote_mngr;
45 PhotosModeController *mode_cntrlr;
46 GtkListBox *listbox;
47 gchar *urn;
48 };
49
50 enum
51 {
52 PROP_0,
53 PROP_URN
54 };
55
56
57 G_DEFINE_TYPE (PhotosDlnaRenderersDialog, photos_dlna_renderers_dialog, GTK_TYPE_DIALOG);
58
59
60 static void
photos_dlna_renderers_dialog_row_activated_cb(PhotosDlnaRenderersDialog * self,GtkListBoxRow * row,gpointer user_data)61 photos_dlna_renderers_dialog_row_activated_cb (PhotosDlnaRenderersDialog *self,
62 GtkListBoxRow *row,
63 gpointer user_data)
64 {
65 PhotosBaseItem *item;
66 PhotosDlnaRenderer *renderer;
67
68 renderer = g_object_get_data (G_OBJECT (row), "renderer");
69 item = PHOTOS_BASE_ITEM (photos_base_manager_get_object_by_id (self->item_mngr,
70 self->urn));
71 photos_remote_display_manager_set_renderer (self->remote_mngr, renderer);
72 photos_remote_display_manager_render (self->remote_mngr, item);
73
74 photos_mode_controller_go_back (self->mode_cntrlr);
75
76 gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
77 }
78
79
80 static void
photos_dlna_renderers_dialog_dispose(GObject * object)81 photos_dlna_renderers_dialog_dispose (GObject *object)
82 {
83 PhotosDlnaRenderersDialog *self = PHOTOS_DLNA_RENDERERS_DIALOG (object);
84
85 g_clear_object (&self->item_mngr);
86 g_clear_object (&self->renderers_mngr);
87 g_clear_object (&self->remote_mngr);
88 g_clear_object (&self->mode_cntrlr);
89
90 G_OBJECT_CLASS (photos_dlna_renderers_dialog_parent_class)->dispose (object);
91 }
92
93
94 static void
photos_dlna_renderers_dialog_finalize(GObject * object)95 photos_dlna_renderers_dialog_finalize (GObject *object)
96 {
97 PhotosDlnaRenderersDialog *self = PHOTOS_DLNA_RENDERERS_DIALOG (object);
98
99 g_free (self->urn);
100
101 G_OBJECT_CLASS (photos_dlna_renderers_dialog_parent_class)->finalize (object);
102 }
103
104
105 static void
photos_dlna_renderers_dialog_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)106 photos_dlna_renderers_dialog_set_property (GObject *object,
107 guint prop_id,
108 const GValue *value,
109 GParamSpec *pspec)
110 {
111 PhotosDlnaRenderersDialog *self = PHOTOS_DLNA_RENDERERS_DIALOG (object);
112
113 switch (prop_id)
114 {
115 case PROP_URN:
116 self->urn = g_value_dup_string (value);
117 break;
118
119 default:
120 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
121 break;
122 }
123 }
124
125
126 static void
photos_dlna_renderers_dialog_set_icon_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)127 photos_dlna_renderers_dialog_set_icon_cb (GObject *source_object,
128 GAsyncResult *res,
129 gpointer user_data)
130 {
131 GdkPixbuf *pixbuf;
132 GtkImage *image = GTK_IMAGE (user_data);
133 PhotosDlnaRenderer *renderer = PHOTOS_DLNA_RENDERER (source_object);
134 GError *error = NULL;
135
136 pixbuf = photos_dlna_renderer_get_icon_finish (renderer, res, &error);
137 if (error != NULL)
138 {
139 g_warning ("Unable to load renderer icon: %s", error->message);
140 g_error_free (error);
141 goto out;
142 }
143
144 gtk_image_set_from_pixbuf (image, pixbuf);
145
146 out:
147 /* release the ref we took before the async call */
148 g_object_unref (image);
149 }
150
151
152 static void
photos_dlna_renderers_dialog_add_renderer(PhotosDlnaRenderersDialog * self,PhotosDlnaRenderer * renderer)153 photos_dlna_renderers_dialog_add_renderer (PhotosDlnaRenderersDialog *self, PhotosDlnaRenderer *renderer)
154 {
155 GIcon *icon;
156 GtkWidget *row;
157 GtkWidget *row_grid;
158 GtkWidget *image;
159 GtkWidget *label;
160 const gchar *name;
161
162 row = gtk_list_box_row_new ();
163 gtk_container_add (GTK_CONTAINER (self->listbox), row);
164
165 row_grid = gtk_grid_new ();
166 gtk_container_set_border_width (GTK_CONTAINER (row_grid), 12);
167 gtk_orientable_set_orientation (GTK_ORIENTABLE (row_grid), GTK_ORIENTATION_HORIZONTAL);
168 gtk_grid_set_column_spacing (GTK_GRID (row_grid), 12);
169 gtk_container_add (GTK_CONTAINER (row), row_grid);
170
171 g_object_set_data_full (G_OBJECT (row), "renderer", g_object_ref (renderer), g_object_unref);
172
173 name = photos_dlna_renderer_get_friendly_name (renderer);
174
175 icon = g_themed_icon_new_with_default_fallbacks ("video-display-symbolic");
176 image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
177
178 g_object_ref (image); /* keep a ref for the following async call and release it in the callback */
179 photos_dlna_renderer_get_icon (renderer,
180 "",
181 "",
182 GTK_ICON_SIZE_DIALOG,
183 NULL,
184 photos_dlna_renderers_dialog_set_icon_cb,
185 image);
186
187 gtk_container_add (GTK_CONTAINER (row_grid), image);
188
189 label = gtk_label_new (NULL);
190 gtk_label_set_text (GTK_LABEL (label), name);
191 gtk_container_add (GTK_CONTAINER (row_grid), label);
192 }
193
194
195 static void
photos_dlna_renderers_dialog_init(PhotosDlnaRenderersDialog * self)196 photos_dlna_renderers_dialog_init (PhotosDlnaRenderersDialog *self)
197 {
198 GApplication *app;
199 GList *renderers;
200 PhotosSearchContextState *state;
201
202 app = g_application_get_default ();
203 state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
204
205 self->item_mngr = g_object_ref (state->item_mngr);
206 self->renderers_mngr = photos_dlna_renderers_manager_dup_singleton ();
207 self->remote_mngr = photos_remote_display_manager_dup_singleton ();
208 self->mode_cntrlr = g_object_ref (state->mode_cntrlr);
209
210 gtk_widget_init_template (GTK_WIDGET (self));
211
212 gtk_list_box_set_header_func (self->listbox, photos_utils_list_box_header_func, NULL, NULL);
213
214 renderers = photos_dlna_renderers_manager_dup_renderers (self->renderers_mngr);
215
216 while (renderers != NULL)
217 {
218 PhotosDlnaRenderer *renderer = PHOTOS_DLNA_RENDERER (renderers->data);
219
220 photos_dlna_renderers_dialog_add_renderer (self, renderer);
221 renderers = g_list_delete_link (renderers, renderers);
222 g_object_unref (renderer);
223 }
224
225 g_signal_connect (self, "response", G_CALLBACK (gtk_widget_destroy), NULL);
226 }
227
228
229 static void
photos_dlna_renderers_dialog_class_init(PhotosDlnaRenderersDialogClass * class)230 photos_dlna_renderers_dialog_class_init (PhotosDlnaRenderersDialogClass *class)
231 {
232 GObjectClass *object_class = G_OBJECT_CLASS (class);
233 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
234
235 object_class->dispose = photos_dlna_renderers_dialog_dispose;
236 object_class->finalize = photos_dlna_renderers_dialog_finalize;
237 object_class->set_property = photos_dlna_renderers_dialog_set_property;
238
239 g_object_class_install_property (object_class,
240 PROP_URN,
241 g_param_spec_string ("urn",
242 "Uniform Resource Name",
243 "An unique ID associated with this item",
244 NULL,
245 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
246
247 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Photos/dlna-renderers-dialog.ui");
248
249 gtk_widget_class_bind_template_child (widget_class, PhotosDlnaRenderersDialog, listbox);
250 gtk_widget_class_bind_template_callback (widget_class, photos_dlna_renderers_dialog_row_activated_cb);
251 }
252
253
254 GtkWidget *
photos_dlna_renderers_dialog_new(GtkWindow * parent,const gchar * urn)255 photos_dlna_renderers_dialog_new (GtkWindow *parent, const gchar *urn)
256 {
257 g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
258
259 return g_object_new (PHOTOS_TYPE_DLNA_RENDERERS_DIALOG,
260 "transient-for", parent,
261 "urn", urn,
262 "use-header-bar", TRUE,
263 NULL);
264 }
265