1 /*
2  * Copyright (C) 2007 Felipe Weckx <felipe.weckx@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #include "gbemol-mpd.h"
21 #include "gbemol-info.h"
22 #include "gbemol-utils.h"
23 
24 static GObjectClass *parent_class = NULL;
25 
26 struct _GbemolInfoPrivate {
27 	GbemolMpd* mpd;
28 
29 	GtkWidget* lbl_title;
30 	GtkWidget* lbl_track;
31 	GtkWidget* lbl_genre;
32 	GtkWidget* lbl_date;
33 	GtkWidget* lbl_composer;
34 	GtkWidget* lbl_performer;
35 	GtkWidget* lbl_disc;
36 	GtkWidget* lbl_comment;
37 	GtkWidget* img_info;
38 	GtkWidget* vbox_info;
39 	GtkWidget* vp;
40 
41 	gboolean dispose_has_run;
42 
43 	gint mode;
44 };
45 
46 /* Constructors/Destructors */
47 static void gbemol_info_class_init (GObjectClass *g_class);
48 static void gbemol_info_init (GbemolInfo *obj);
49 static void gbemol_info_finalize (GObject *object);
50 static void gbemol_info_dispose (GObject *object);
51 
52 /* Class functions */
53 
54 static void gbemol_info_set_mode (GbemolInfo* info, gint mode);
55 static void gbemol_info_set_song_mode (GbemolInfo* info);
56 static void gbemol_info_set_image (GbemolInfo* info, GdkPixbuf* img);
57 
58 /* Callbacks */
59 static void on_info_style_set (GtkWidget *widget, GtkStyle *style, GtkWidget* event);
60 static void on_info_style_set_vp (GtkWidget *widget, GtkStyle *style, GtkWidget* vp);
61 static void on_info_style_set_hbox (GtkWidget *widget, GtkStyle *style, GtkWidget* hbox);
62 
63 GType
gbemol_info_get_type(void)64 gbemol_info_get_type (void)
65 {
66 	static GType type = 0;
67 	if (type == 0) {
68 		static const GTypeInfo info = {
69 			sizeof (GbemolInfoClass),
70 			NULL,   /* base_init */
71 			NULL,   /* base_finalize */
72 			(GClassInitFunc) gbemol_info_class_init,   /* class_init */
73 			NULL,   /* class_finalize */
74 			NULL,   /* class_data */
75 			sizeof (GbemolInfo),
76 			0,      /* n_preallocs */
77 			(GInstanceInitFunc) gbemol_info_init    /* instance_init */
78 		};
79 
80 		type = g_type_register_static (GTK_TYPE_EVENT_BOX,
81 				"GbemolInfo",
82 				&info, 0);
83 	}
84 	return type;
85 }
86 
87 static void
gbemol_info_class_init(GObjectClass * g_class)88 gbemol_info_class_init (GObjectClass *g_class)
89 {
90 	parent_class = g_type_class_peek_parent (g_class);
91 	g_class->finalize = gbemol_info_finalize;
92 	g_class->dispose = gbemol_info_dispose;
93 }
94 
95 static void
gbemol_info_dispose(GObject * obj)96 gbemol_info_dispose (GObject* obj)
97 {
98 	GbemolInfo* self = (GbemolInfo *) obj;
99 
100 	if (self->priv->dispose_has_run)
101 		return;
102 	self->priv->dispose_has_run = TRUE;
103 
104 	G_OBJECT_CLASS (parent_class)->dispose (obj);
105 
106 }
107 
108 static void
gbemol_info_finalize(GObject * obj)109 gbemol_info_finalize (GObject *obj)
110 {
111 	g_free (GBEMOL_INFO (obj)->priv);
112 	G_OBJECT_CLASS (parent_class)->finalize (obj);
113 }
114 
115 static void
gbemol_info_init(GbemolInfo * obj)116 gbemol_info_init (GbemolInfo *obj)
117 {
118 	obj->priv = g_new0 (GbemolInfoPrivate, 1);
119 	obj->priv->dispose_has_run = FALSE;
120 }
121 
122 GbemolInfo*
gbemol_info_new(GbemolMpd * mpd)123 gbemol_info_new (GbemolMpd* mpd)
124 {
125 	GbemolInfo *info;
126 	GtkWidget *vbox, *hbox, *scr, *event;
127 
128 	info = GBEMOL_INFO (g_object_new (GBEMOL_TYPE_INFO, NULL));
129 	info->priv->mpd = mpd;
130 	info->priv->mode = 0;
131 
132 	vbox = gtk_vbox_new (FALSE, 5);
133 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
134 
135 	/* Set Backgound Color */
136 	gtk_widget_set_app_paintable (GTK_WIDGET (info), TRUE);
137 	g_signal_connect (G_OBJECT (vbox), "style-set", G_CALLBACK (on_info_style_set), info);
138 	gtk_container_add (GTK_CONTAINER (info), vbox);
139 
140 	event = gtk_event_box_new ();
141 	gtk_widget_set_app_paintable (event, TRUE);
142 	g_signal_connect (G_OBJECT (vbox), "style-set", G_CALLBACK (on_info_style_set_hbox), event);
143 	gtk_box_pack_start (GTK_BOX (vbox), event, FALSE, FALSE, 5);
144 
145 	hbox = gtk_hbox_new (FALSE, 5);
146 	gtk_container_add (GTK_CONTAINER (event), hbox);
147 
148 	info->priv->lbl_title = gtk_label_new ("");
149 	gtk_box_pack_start (GTK_BOX (hbox), info->priv->lbl_title, FALSE, FALSE, 10);
150 
151 	info->priv->img_info = gtk_image_new ();
152 	gtk_box_pack_end (GTK_BOX (hbox), info->priv->img_info, FALSE, FALSE, 5);
153 
154 	scr = gtk_scrolled_window_new (NULL, NULL);
155 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
156 	gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
157 
158 	info->priv->vp = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scr)),
159 				gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scr)));
160 	gtk_widget_set_app_paintable (info->priv->vp, TRUE);
161 	gtk_container_add (GTK_CONTAINER (scr), info->priv->vp);
162 	g_signal_connect (G_OBJECT (vbox), "style-set", G_CALLBACK (on_info_style_set_vp), info->priv->vp);
163 
164 	info->priv->vbox_info = gtk_vbox_new (FALSE, 0);
165 	gtk_container_add (GTK_CONTAINER (info->priv->vp), info->priv->vbox_info);
166 
167 	gtk_widget_show_all (GTK_WIDGET (info));
168 
169 	return info;
170 }
171 
172 static void
gbemol_info_set_song_mode(GbemolInfo * info)173 gbemol_info_set_song_mode (GbemolInfo* info)
174 {
175 	GtkWidget *table, *lbl;
176 
177 	table = gtk_table_new (7, 2, TRUE);
178 	gtk_table_set_row_spacings (GTK_TABLE (table), 3);
179 	gtk_table_set_col_spacings (GTK_TABLE (table), 3);
180 
181 	lbl = gbemol_utils_label_new_with_markup (_("<b>Track</b>"));
182 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 3, 3);
183 	info->priv->lbl_track = gbemol_utils_label_new_with_markup ("");
184 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_track, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 3, 3);
185 
186 	lbl = gbemol_utils_label_new_with_markup (_("<b>Genre</b>"));
187 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 3, 3);
188 	info->priv->lbl_genre = gbemol_utils_label_new_with_markup ("");
189 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_genre, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 3, 3);
190 
191 	lbl = gbemol_utils_label_new_with_markup (_("<b>Date</b>"));
192 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 3, 3);
193 	info->priv->lbl_date = gbemol_utils_label_new_with_markup ("");
194 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_date, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 3, 3);
195 
196 	lbl = gbemol_utils_label_new_with_markup (_("<b>Composer</b>"));
197 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 3, 3);
198 	info->priv->lbl_composer = gbemol_utils_label_new_with_markup ("");
199 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_composer, 1, 2, 3, 4, GTK_FILL, GTK_FILL, 3, 3);
200 
201 	lbl = gbemol_utils_label_new_with_markup (_("<b>Performer</b>"));
202 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 3, 3);
203 	info->priv->lbl_performer = gbemol_utils_label_new_with_markup ("");
204 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_performer, 1, 2, 4, 5, GTK_FILL, GTK_FILL, 3, 3);
205 
206 	lbl = gbemol_utils_label_new_with_markup (_("<b>Disc</b>"));
207 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 3, 3);
208 	info->priv->lbl_disc = gbemol_utils_label_new_with_markup ("");
209 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_disc, 1, 2, 5, 6, GTK_FILL, GTK_FILL, 3, 3);
210 
211 	lbl = gbemol_utils_label_new_with_markup (_("<b>Comment</b>"));
212 	gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 6, 7, GTK_FILL, GTK_FILL, 3, 3);
213 	info->priv->lbl_comment = gbemol_utils_label_new_with_markup ("");
214 	gtk_table_attach (GTK_TABLE (table), info->priv->lbl_comment, 1, 2, 6, 7, GTK_FILL, GTK_FILL, 3, 3);
215 
216 	gtk_box_pack_start (GTK_BOX (info->priv->vbox_info), table, FALSE, FALSE, 0);
217 }
218 
219 
220 static void
gbemol_info_set_mode(GbemolInfo * info,gint mode)221 gbemol_info_set_mode (GbemolInfo* info, gint mode)
222 {
223 	if (mode == info->priv->mode)
224 		return;
225 
226 	/* Destroy current widgets */
227 	gtk_widget_destroy (info->priv->vbox_info);
228 
229 	info->priv->vbox_info = gtk_vbox_new (FALSE, 0);
230 	gtk_container_add (GTK_CONTAINER (info->priv->vp), info->priv->vbox_info);
231 
232 	switch (mode)
233 	{
234 		case INFO_MODE_SONG:
235 			gbemol_info_set_song_mode (info);
236 			break;
237 		case INFO_MODE_ALBUM:
238 			break;
239 		case INFO_MODE_ARTIST:
240 			break;
241 	}
242 
243 	gtk_widget_show_all (info->priv->vbox_info);
244 }
245 
246 static void
gbemol_info_set_image(GbemolInfo * info,GdkPixbuf * img)247 gbemol_info_set_image (GbemolInfo* info, GdkPixbuf* img)
248 {
249 	GdkPixbuf* scaled;
250 
251 	if (img)
252 	{
253 		scaled = gdk_pixbuf_scale_simple (img, 100, 100, GDK_INTERP_BILINEAR);
254 		gtk_image_set_from_pixbuf (GTK_IMAGE (info->priv->img_info), scaled);
255 		g_object_unref (img);
256 		g_object_unref (scaled);
257 		gtk_widget_show (info->priv->img_info);
258 	}
259 	else
260 		gtk_widget_hide (info->priv->img_info);
261 }
262 
263 /* Set a song info in the info tab */
264 void
gbemol_info_set_song(GbemolInfo * info,GbemolMpdSong * song)265 gbemol_info_set_song (GbemolInfo* info, GbemolMpdSong* song)
266 {
267 	gchar *str;
268 
269 	if (!song)
270 		return;
271 
272 	gbemol_info_set_mode (info, INFO_MODE_SONG);
273 
274 	if (song->title != NULL)
275 		str = g_markup_printf_escaped (_("<span size=\"xx-large\" weight=\"ultrabold\">%s</span>\n"
276 					"by <b>%s</b> from <b>%s</b>"), song->title, song->artist, song->album);
277 	else
278 		str = g_markup_printf_escaped (_("<span size=\"xx-large\" weight=\"ultrabold\">%s</span>"), song->name);
279 	gtk_label_set_markup (GTK_LABEL (info->priv->lbl_title), str);
280 	g_free (str);
281 
282 	if (song->track != NULL)
283 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_track), song->track);
284 	else
285 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_track), _("Unknown"));
286 	if (song->genre != NULL)
287 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_genre), song->genre);
288 	else
289 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_genre), _("Unknown"));
290 	if (song->date != NULL)
291 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_date), song->date);
292 	else
293 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_date), _("Unknown"));
294 	if (song->composer != NULL)
295 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_composer), song->composer);
296 	else
297 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_composer), _("Unknown"));
298 	if (song->performer != NULL)
299 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_performer), song->performer);
300 	else
301 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_performer), _("Unknown"));
302 	if (song->disc != NULL)
303 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_disc), song->disc);
304 	else
305 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_disc), _("Unknown"));
306 	if (song->comment != NULL)
307 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_comment), song->comment);
308 	else
309 		gtk_label_set_text (GTK_LABEL (info->priv->lbl_comment), _("Unknown"));
310 
311 	gbemol_info_set_image (info, gbemol_utils_get_song_image (song));
312 }
313 
314 void
gbemol_info_set_album(GbemolInfo * info,gchar * album,gchar * artist)315 gbemol_info_set_album (GbemolInfo* info, gchar* album, gchar* artist)
316 {
317 	gchar *str;
318 	GList* songs;
319 	GtkWidget* lbl;
320 	GbemolMpdSong* song;
321 	gint time = 0;
322 
323 	gbemol_info_set_mode (info, INFO_MODE_ALBUM);
324 
325 	str = g_markup_printf_escaped ("<span size=\"x-large\" weight=\"heavy\">%s</span><b>  by  </b>"
326 					"<span size=\"x-large\" weight=\"heavy\">%s</span>", album, artist);
327 	gtk_label_set_markup (GTK_LABEL (info->priv->lbl_title), str);
328 	g_free (str);
329 
330 	/* Get the album songs */
331 	gbemol_mpd_search_start (info->priv->mpd);
332 	gbemol_mpd_search_add_constraint (info->priv->mpd, MPD_TAG_ITEM_ARTIST, artist);
333 	gbemol_mpd_search_add_constraint (info->priv->mpd, MPD_TAG_ITEM_ALBUM, album);
334 	songs = gbemol_mpd_search_get_results (info->priv->mpd);
335 
336 	do
337 	{
338 		song = songs->data;
339 		if (song->time != MPD_SONG_NO_TIME)
340 			time += song->time;
341 		str = g_strdup_printf ("%s %s", song->track, song->title);
342 		lbl = gbemol_utils_label_new_with_markup (str);
343 		gtk_box_pack_start (GTK_BOX (info->priv->vbox_info), lbl, FALSE, FALSE, 3);
344 		g_free (str);
345 		gtk_widget_show (lbl);
346 	} while ((songs = g_list_next (songs)));
347 
348 	if (time > 3600)
349 		str = g_markup_printf_escaped (_("\n<b>Total Time: </b> %02d:%02d:%02d"), time/3600,
350 				(time%3600)/60, (time%3600)%60);
351 	else
352 		str = g_markup_printf_escaped (_("\n<b>Total Time: </b> %02d:%02d"), time/60, time%60);
353 
354 	lbl = gbemol_utils_label_new_with_markup (str);
355 	gtk_box_pack_start (GTK_BOX (info->priv->vbox_info), lbl, FALSE, FALSE, 5);
356 	g_free (str);
357 	gtk_widget_show (lbl);
358 
359 	gbemol_mpd_free_song_list (songs);
360 }
361 
gbemol_info_set_artist(GbemolInfo * info,gchar * artist)362 void gbemol_info_set_artist (GbemolInfo* info, gchar* artist)
363 {
364 	GList *albums;
365 	GtkWidget* lbl;
366 	gchar *str;
367 
368 	gbemol_info_set_mode (info, INFO_MODE_ARTIST);
369 
370 	str = g_markup_printf_escaped ("<span size=\"xx-large\" weight=\"heavy\">%s</span>", artist);
371 	gtk_label_set_markup (GTK_LABEL (info->priv->lbl_title), str);
372 	g_free (str);
373 
374 	/* Find all the albums by artist */
375 	gbemol_mpd_search_field_start (info->priv->mpd, MPD_TABLE_ALBUM);
376 	gbemol_mpd_search_add_constraint (info->priv->mpd, MPD_TABLE_ARTIST, artist);
377 	albums = gbemol_mpd_search_field_get_results (info->priv->mpd, MPD_TABLE_ALBUM);
378 
379 	str = g_markup_printf_escaped ("<span size=\"large\" weight=\"bold\">Albums by %s\n</span>", artist);
380 	lbl = gbemol_utils_label_new_with_markup (str);
381 	gtk_box_pack_start (GTK_BOX (info->priv->vbox_info), lbl, FALSE, FALSE, 3);
382 	gtk_widget_show (lbl);
383 	g_free (str);
384 
385 	do
386 	{
387 		str = albums->data;
388 		lbl = gbemol_utils_label_new_with_markup (str);
389 		gtk_box_pack_start (GTK_BOX (info->priv->vbox_info), lbl, FALSE, FALSE, 3);
390 		g_free (str);
391 		gtk_widget_show (lbl);
392 	} while ((albums = g_list_next (albums)));
393 
394 	gbemol_utils_char_list_free (albums);
395 }
396 
397 static void
on_info_style_set(GtkWidget * widget,GtkStyle * style,GtkWidget * event)398 on_info_style_set (GtkWidget *widget, GtkStyle *style, GtkWidget* event)
399 {
400 	gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(widget->style->base[GTK_STATE_NORMAL]));
401 }
402 
403 static void
on_info_style_set_vp(GtkWidget * widget,GtkStyle * style,GtkWidget * vp)404 on_info_style_set_vp (GtkWidget *widget, GtkStyle *style, GtkWidget* vp)
405 {
406 	gtk_widget_modify_bg(vp, GTK_STATE_NORMAL, &(widget->style->base[GTK_STATE_NORMAL]));
407 }
408 
409 static void
on_info_style_set_hbox(GtkWidget * widget,GtkStyle * style,GtkWidget * vp)410 on_info_style_set_hbox (GtkWidget *widget, GtkStyle *style, GtkWidget* vp)
411 {
412 	gtk_widget_modify_bg(vp, GTK_STATE_NORMAL, &(widget->style->base[GTK_STATE_SELECTED]));
413 }
414 
415 
416