comparison src/audacious/ui_fileinfopopup.c @ 2348:564e8a1fe09a trunk

[svn] - made a public API for fileinfopopup (popup that displays metadata, the same used in playlist); now plugins can include ui_fileinfopopup.h to display metadata popups (i.e. statusicon and libnotify plugins)
author giacomo
date Tue, 16 Jan 2007 10:33:13 -0800
parents
children 911743d27aba
comparison
equal deleted inserted replaced
2347:74bbc3e18cba 2348:564e8a1fe09a
1 /*
2 * Audacious: A cross-platform multimedia player
3 * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
4 * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
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; under version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <glib.h>
26 #include <glib/gi18n.h>
27 #include <gtk/gtk.h>
28 #include <glade/glade.h>
29 #include <string.h>
30
31 #include "glade.h"
32 #include "titlestring.h"
33 #include "ui_fileinfopopup.h"
34 #include "main.h"
35 #include "ui_main.h"
36
37
38 static void
39 filepopup_entry_set_text(GtkWidget *filepopup_win, const char *entry, const char *text)
40 {
41 GladeXML *xml = g_object_get_data(G_OBJECT(filepopup_win), "glade-xml");
42 GtkWidget *widget = glade_xml_get_widget(xml, entry);
43
44 if (xml == NULL || widget == NULL)
45 return;
46
47 gtk_label_set_text(GTK_LABEL(widget), text);
48 }
49
50 static void
51 filepopup_entry_set_image(GtkWidget *filepopup_win, const char *entry, const char *text)
52 {
53 GladeXML *xml = g_object_get_data(G_OBJECT(filepopup_win), "glade-xml");
54 GtkWidget *widget = glade_xml_get_widget(xml, entry);
55 GdkPixbuf *pixbuf;
56 int width, height;
57 double aspect;
58 GdkPixbuf *pixbuf2;
59
60 if (xml == NULL || widget == NULL)
61 return;
62
63 pixbuf = gdk_pixbuf_new_from_file(text, NULL);
64
65 if (pixbuf == NULL)
66 return;
67
68 width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf));
69 height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf));
70
71 if(strcmp(DATA_DIR "/images/audio.png", text))
72 {
73 if(width == 0)
74 width = 1;
75 aspect = (double)height / (double)width;
76 if(aspect > 1.0) {
77 height = (int)(cfg.filepopup_pixelsize * aspect);
78 width = cfg.filepopup_pixelsize;
79 } else {
80 height = cfg.filepopup_pixelsize;
81 width = (int)(cfg.filepopup_pixelsize / aspect);
82 }
83 pixbuf2 = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), width, height, GDK_INTERP_BILINEAR);
84 g_object_unref(G_OBJECT(pixbuf));
85 pixbuf = pixbuf2;
86 }
87
88 gtk_image_set_from_pixbuf(GTK_IMAGE(widget), GDK_PIXBUF(pixbuf));
89 g_object_unref(G_OBJECT(pixbuf));
90 }
91
92 static void
93 filepopup_entry_set_text_free(GtkWidget *filepopup_win, const char *entry, char *text)
94 {
95 GladeXML *xml = g_object_get_data(G_OBJECT(filepopup_win), "glade-xml");
96 GtkWidget *widget = glade_xml_get_widget(xml, entry);
97
98 if (xml == NULL || widget == NULL)
99 return;
100
101 gtk_label_set_text(GTK_LABEL(widget), text);
102
103 g_free(text);
104 }
105
106 static gboolean
107 has_front_cover_extension(const gchar *name)
108 {
109 char *ext;
110
111 ext = strrchr(name, '.');
112 if (!ext) {
113 /* No file extension */
114 return FALSE;
115 }
116
117 return g_strcasecmp(ext, ".jpg") == 0 ||
118 g_strcasecmp(ext, ".jpeg") == 0 ||
119 g_strcasecmp(ext, ".png") == 0;
120 }
121
122 static gboolean
123 cover_name_filter(const gchar *name, const gchar *filter, const gboolean ret_on_empty)
124 {
125 gboolean result = FALSE;
126 gchar **splitted;
127 gchar *current;
128 gchar *lname;
129 gint i;
130
131 if (!filter || strlen(filter) == 0) {
132 return ret_on_empty;
133 }
134
135 splitted = g_strsplit(filter, ",", 0);
136
137 lname = g_strdup(name);
138 g_strdown(lname);
139
140 for (i = 0; !result && (current = splitted[i]); i++) {
141 gchar *stripped = g_strstrip(g_strdup(current));
142 g_strdown(stripped);
143
144 result = result || strstr(lname, stripped);
145
146 g_free(stripped);
147 }
148
149 g_free(lname);
150 g_strfreev(splitted);
151
152 return result;
153 }
154
155 /* Check wether it's an image we want */
156 static gboolean
157 is_front_cover_image(const gchar *imgfile)
158 {
159 return cover_name_filter(imgfile, cfg.cover_name_include, TRUE) &&
160 !cover_name_filter(imgfile, cfg.cover_name_exclude, FALSE);
161 }
162
163 static gboolean
164 is_file_image(const gchar *imgfile, const gchar *file_name)
165 {
166 char *imgfile_ext, *file_name_ext;
167 size_t imgfile_len, file_name_len;
168
169 imgfile_ext = strrchr(imgfile, '.');
170 if (!imgfile_ext) {
171 /* No file extension */
172 return FALSE;
173 }
174
175 file_name_ext = strrchr(file_name, '.');
176 if (!file_name_ext) {
177 /* No file extension */
178 return FALSE;
179 }
180
181 imgfile_len = (imgfile_ext - imgfile);
182 file_name_len = (file_name_ext - file_name);
183
184 if (imgfile_len == file_name_len) {
185 return (g_ascii_strncasecmp(imgfile, file_name, imgfile_len) == 0);
186 } else {
187 return FALSE;
188 }
189 }
190
191 static gchar*
192 fileinfo_recursive_get_image(const gchar* path,
193 const gchar* file_name, gint depth)
194 {
195 GDir *d;
196
197 if (cfg.recurse_for_cover && depth > cfg.recurse_for_cover_depth)
198 return NULL;
199
200 d = g_dir_open(path, 0, NULL);
201
202 if (d) {
203 const gchar *f;
204
205 if (cfg.use_file_cover && file_name) {
206 /* Look for images matching file name */
207 while((f = g_dir_read_name(d))) {
208 gchar *newpath = g_strconcat(path, "/", f, NULL);
209
210 if (!g_file_test(newpath, G_FILE_TEST_IS_DIR) &&
211 has_front_cover_extension(f) &&
212 is_file_image(f, file_name)) {
213 g_dir_close(d);
214 return newpath;
215 }
216
217 g_free(newpath);
218 }
219 g_dir_rewind(d);
220 }
221
222 /* Search for files using filter */
223 while ((f = g_dir_read_name(d))) {
224 gchar *newpath = g_strconcat(path, "/", f, NULL);
225
226 if (!g_file_test(newpath, G_FILE_TEST_IS_DIR) &&
227 has_front_cover_extension(f) &&
228 is_front_cover_image(f)) {
229 g_dir_close(d);
230 return newpath;
231 }
232
233 g_free(newpath);
234 }
235 g_dir_rewind(d);
236
237 /* checks whether recursive or not. */
238 if (!cfg.recurse_for_cover) {
239 g_dir_close(d);
240 return NULL;
241 }
242
243 /* Descend into directories recursively. */
244 while ((f = g_dir_read_name(d))) {
245 gchar *newpath = g_strconcat(path, "/", f, NULL);
246
247 if(g_file_test(newpath, G_FILE_TEST_IS_DIR)) {
248 gchar *tmp = fileinfo_recursive_get_image(newpath,
249 NULL, depth + 1);
250 if(tmp) {
251 g_free(newpath);
252 g_dir_close(d);
253 return tmp;
254 }
255 }
256
257 g_free(newpath);
258 }
259
260 g_dir_close(d);
261 }
262
263 return NULL;
264 }
265
266
267
268 GtkWidget *
269 audacious_fileinfopopup_create(void)
270 {
271 const gchar *glade_file = DATA_DIR "/glade/fileinfo_popup.glade";
272 GladeXML *xml;
273 GtkWidget *widget;
274 GtkWidget *filepopup_win;
275
276 xml = glade_xml_new_or_die(_("Track Information Popup"), glade_file, NULL, NULL);
277
278 glade_xml_signal_autoconnect(xml);
279
280 filepopup_win = glade_xml_get_widget(xml, "win_pl_popup");
281 g_object_set_data(G_OBJECT(filepopup_win), "glade-xml", xml);
282 gtk_window_set_transient_for(GTK_WINDOW(filepopup_win), GTK_WINDOW(mainwin));
283
284 widget = glade_xml_get_widget(xml, "image_artwork");
285 gtk_image_set_from_file(GTK_IMAGE(widget), DATA_DIR "/images/audio.png");
286 g_object_set_data( G_OBJECT(filepopup_win) , "last_artwork" , NULL );
287
288 return filepopup_win;
289 }
290
291 void
292 audacious_fileinfopopup_destroy(GtkWidget *filepopup_win)
293 {
294 gchar *last_artwork = g_object_get_data( G_OBJECT(filepopup_win) , "last_artwork" );
295 if ( last_artwork != NULL ) g_free(last_artwork);
296 g_object_unref( g_object_get_data(G_OBJECT(filepopup_win), "glade-xml") );
297 gtk_widget_destroy( filepopup_win );
298 return;
299 }
300
301 void
302 audacious_fileinfopopup_show_from_tuple(GtkWidget *filepopup_win, TitleInput *tuple)
303 {
304 gchar *tmp = NULL;
305 gint x, y, x_off = 3, y_off = 3, h, w;
306
307 gchar *last_artwork = g_object_get_data( G_OBJECT(filepopup_win) , "last_artwork" );
308 const static char default_artwork[] = DATA_DIR "/images/audio.png";
309
310 if (tuple == NULL)
311 return;
312
313 gtk_widget_realize(filepopup_win);
314
315 filepopup_entry_set_text(filepopup_win, "label_title", tuple->track_name);
316 filepopup_entry_set_text(filepopup_win, "label_artist", tuple->performer);
317 filepopup_entry_set_text(filepopup_win, "label_album", tuple->album_name);
318 filepopup_entry_set_text(filepopup_win, "label_genre", tuple->genre);
319
320 if (tuple->length != -1)
321 filepopup_entry_set_text_free(filepopup_win, "label_length", g_strdup_printf("%d:%02d", tuple->length / 60000, (tuple->length / 1000) % 60));
322
323 if (tuple->year != 0)
324 filepopup_entry_set_text_free(filepopup_win, "label_year", g_strdup_printf("%d", tuple->year));
325
326 if (tuple->track_number != 0)
327 filepopup_entry_set_text_free(filepopup_win, "label_track", g_strdup_printf("%d", tuple->track_number));
328
329 tmp = fileinfo_recursive_get_image(tuple->file_path, tuple->file_name, 0);
330 if (tmp) { // picture found
331 if (!last_artwork || strcmp(last_artwork, tmp)) { // new picture
332 filepopup_entry_set_image(filepopup_win, "image_artwork", tmp);
333 if (last_artwork) g_free(last_artwork);
334 last_artwork = tmp;
335 g_object_set_data( G_OBJECT(filepopup_win) , "last_artwork" , last_artwork );
336 }
337 else { // same picture
338 }
339 }
340 else { // no picture found
341 if (!last_artwork || strcmp(last_artwork, default_artwork)) {
342 filepopup_entry_set_image(filepopup_win, "image_artwork", default_artwork);
343 if (last_artwork) g_free(last_artwork);
344 last_artwork = g_strdup(default_artwork);
345 g_object_set_data( G_OBJECT(filepopup_win) , "last_artwork" , last_artwork );
346 }
347 else {
348 }
349 }
350
351 gdk_window_get_pointer(NULL, &x, &y, NULL);
352 gtk_window_get_size(GTK_WINDOW(filepopup_win), &w, &h);
353 if (gdk_screen_width()-(w+3) < x) x_off = (w*-1)-3;
354 if (gdk_screen_height()-(h+3) < y) y_off = (h*-1)-3;
355 gtk_window_move(GTK_WINDOW(filepopup_win), x + x_off, y + y_off);
356
357 gtk_widget_show(filepopup_win);
358 }
359
360
361 void
362 audacious_fileinfopopup_hide(GtkWidget *filepopup_win, gpointer unused)
363 {
364 gtk_widget_hide(filepopup_win);
365
366 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_title", "");
367 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_artist", "");
368 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_album", "");
369 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_genre", "");
370 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_track", "");
371 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_year", "");
372 filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_length", "");
373
374 gtk_window_resize(GTK_WINDOW(filepopup_win), 1, 1);
375 }