1 /*
2  * pixbufs.c
3  * Copyright 2010-2012 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions, and the following disclaimer in the documentation
13  *    provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <gdk-pixbuf/gdk-pixbuf.h>
21 
22 #include <libaudcore/audstrings.h>
23 #include <libaudcore/drct.h>
24 #include <libaudcore/probe.h>
25 #include <libaudcore/runtime.h>
26 
27 #include "internal.h"
28 #include "libaudgui-gtk.h"
29 
30 static AudguiPixbuf current_pixbuf;
31 
audgui_pixbuf_fallback()32 EXPORT AudguiPixbuf audgui_pixbuf_fallback ()
33 {
34     static AudguiPixbuf fallback;
35 
36     if (! fallback)
37     {
38         GtkIconTheme * icon_theme = gtk_icon_theme_get_default ();
39         int icon_size = audgui_to_native_dpi (48);
40 
41         fallback.capture (gtk_icon_theme_load_icon (icon_theme,
42          "audio-x-generic", icon_size, (GtkIconLookupFlags) 0, nullptr));
43     }
44 
45     return fallback.ref ();
46 }
47 
audgui_pixbuf_uncache()48 void audgui_pixbuf_uncache ()
49 {
50     current_pixbuf.clear ();
51 }
52 
audgui_pixbuf_scale_within(AudguiPixbuf & pixbuf,int size)53 EXPORT void audgui_pixbuf_scale_within (AudguiPixbuf & pixbuf, int size)
54 {
55     int width = pixbuf.width ();
56     int height = pixbuf.height ();
57 
58     if (width <= size && height <= size)
59         return;
60 
61     if (width > height)
62     {
63         height = size * height / width;
64         width = size;
65     }
66     else
67     {
68         width = size * width / height;
69         height = size;
70     }
71 
72     if (width < 1)
73         width = 1;
74     if (height < 1)
75         height = 1;
76 
77     pixbuf.capture (gdk_pixbuf_scale_simple (pixbuf.get (), width, height, GDK_INTERP_BILINEAR));
78 }
79 
audgui_pixbuf_request(const char * filename,bool * queued)80 EXPORT AudguiPixbuf audgui_pixbuf_request (const char * filename, bool * queued)
81 {
82     AudArtPtr art = aud_art_request (filename, AUD_ART_DATA, queued);
83 
84     auto data = art.data ();
85     return data ? audgui_pixbuf_from_data (data->begin (), data->len ()) : AudguiPixbuf ();
86 }
87 
audgui_pixbuf_request_current(bool * queued)88 EXPORT AudguiPixbuf audgui_pixbuf_request_current (bool * queued)
89 {
90     if (queued)
91         * queued = false;
92 
93     if (! current_pixbuf)
94     {
95         String filename = aud_drct_get_filename ();
96         if (filename)
97             current_pixbuf = audgui_pixbuf_request (filename, queued);
98     }
99 
100     return current_pixbuf.ref ();
101 }
102 
audgui_pixbuf_from_data(const void * data,int64_t size)103 EXPORT AudguiPixbuf audgui_pixbuf_from_data (const void * data, int64_t size)
104 {
105     GdkPixbuf * pixbuf = nullptr;
106     GdkPixbufLoader * loader = gdk_pixbuf_loader_new ();
107     GError * error = nullptr;
108 
109     if (gdk_pixbuf_loader_write (loader, (const unsigned char *) data, size,
110      & error) && gdk_pixbuf_loader_close (loader, & error))
111     {
112         if ((pixbuf = gdk_pixbuf_loader_get_pixbuf (loader)))
113             g_object_ref (pixbuf);
114     }
115     else
116     {
117         AUDWARN ("While loading pixbuf: %s\n", error->message);
118         g_error_free (error);
119     }
120 
121     g_object_unref (loader);
122     return AudguiPixbuf (pixbuf);
123 }
124