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