Color the albums using the hash of artist/album.
[gmpc.git] / src / Providers / RenderCover.vala
blobc42cc4b9b63d14f58a507af354586d7f1163c571
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2011 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 /**
21 * This plugin queries RenderCover.com for artist images (backdrops)
22 * It renders the image to a png (in memory) and passes this as raw data
23 * to the metadata system.
26 using Config;
27 using Gmpc;
28 using Gmpc.Plugin;
29 using Xml;
31 private const bool use_transition_prc = Gmpc.use_transition;
32 private const string some_unique_name_prc = Config.VERSION;
33 private const string log_domain_prc = "Gmpc.Provider.RenderCover";
35 public class Gmpc.Provider.RenderCover:
36 Gmpc.Plugin.Base,Gmpc.Plugin.MetaDataIface
38 private const int[] version = {0,0,2};
40 public override unowned int[] get_version() {
41 return this.version;
44 public override unowned string get_name() {
45 return N_("Backdrop Renderer");
48 construct {
49 this.plugin_type = 8+32;
52 public void set_priority(int priority) {
53 config.set_int(this.get_name(),"priority",priority);
56 public int get_priority() {
57 return config.get_int_with_default(this.get_name(),"priority",100);
60 public void get_metadata(MPD.Song song, Gmpc.MetaData.Type type, MetaDataCallback callback)
63 if(song == null || song.artist == null || song.album == null)
65 log(log_domain_prc, GLib.LogLevelFlags.LEVEL_DEBUG,
66 "Insufficient information. doing nothing");
67 /* Tell that we found nothing */
68 callback(null);
69 return;
71 switch(type)
73 case Gmpc.MetaData.Type.ALBUM_ART:
74 /* A request for artist art came in. */
75 this.get_album_art(song, callback);
76 return;
77 case Gmpc.MetaData.Type.ARTIST_TXT:
78 case Gmpc.MetaData.Type.ARTIST_SIMILAR:
79 case Gmpc.MetaData.Type.ARTIST_ART:
80 case Gmpc.MetaData.Type.ALBUM_TXT:
81 case Gmpc.MetaData.Type.SONG_TXT:
82 case Gmpc.MetaData.Type.SONG_SIMILAR:
83 case Gmpc.MetaData.Type.GENRE_SIMILAR:
84 case Gmpc.MetaData.Type.SONG_GUITAR_TAB:
85 case Gmpc.MetaData.Type.QUERY_DATA_TYPES:
86 case Gmpc.MetaData.Type.QUERY_NO_CACHE:
87 default:
88 break;
91 /* Tell what we found */
92 callback(null);
95 /**
96 * Get album art
98 public const int album_size = 400;
99 private void get_album_art(MPD.Song song, MetaDataCallback callback)
101 Cairo.Pattern p;
102 Cairo.Surface surf = new Cairo.ImageSurface(Cairo.Format.ARGB32, album_size,album_size);
103 Cairo.Context ct = new Cairo.Context(surf);
104 // Color the background based on hash of artist/album.
105 uint hash = song.album.hash();
106 hash+= song.artist.hash();
107 // Background
108 ct.set_source_rgb(
109 (hash&255)/255.0,
110 ((hash>>8)&255)/255.0,
111 ((hash>>16)&255)/255.0);
112 ct.paint();
114 // Header pattern
115 p = new Cairo.Pattern.linear(0, 0, album_size,0);
116 p.add_color_stop_rgb(0, 0.8,0.8,0.8);
117 p.add_color_stop_rgb(1, 0.5,0.5,0.5);
118 ct.set_source(p);
119 ct.rectangle(0.0,0.0,album_size, album_size/3);
120 ct.fill();
122 // Bar
123 p = new Cairo.Pattern.linear(0, 0, album_size,0);
124 p.add_color_stop_rgba(0, 0,0,0,0.1);
125 p.add_color_stop_rgba(0.5, 0,0,0,0.9);
126 p.add_color_stop_rgba(1, 0,0,0,0.1);
127 ct.set_source(p);
128 ct.rectangle(0.0,album_size/3-6,album_size, 12.0);
129 ct.fill();
132 ct.set_source_rgb(0.0,0.0,0.0);
133 Pango.Layout layout = Pango.cairo_create_layout(ct);
134 Pango.FontDescription fd = Pango.FontDescription.from_string("Serif bold 32");
135 layout.set_font_description(fd);
136 layout.set_text(song.album,-1);
137 int aheight=0, awidth=0;
138 layout.get_pixel_size(out awidth, out aheight);
139 if(awidth >= (album_size-50)) {
140 p = new Cairo.Pattern.linear(0, 0, album_size-25,0);
141 p.add_color_stop_rgba(0, 0,0,0,1);
142 p.add_color_stop_rgba((album_size-50)/(double)(album_size), 0,0,0,1);
143 p.add_color_stop_rgba(1, 0,0,0,0.0);
144 ct.set_source(p);
145 }else{
146 ct.set_source_rgb(0.0,0.0,0.0);
148 //layout.set_ellipsize(Pango.EllipsizeMode.END);
150 ct.move_to(25,25);
151 Pango.cairo_layout_path(ct,layout);
152 ct.fill();
154 fd = Pango.FontDescription.from_string("Sans bold 18");
155 layout.set_font_description(fd);
156 layout.set_text(song.artist, -1);
157 int bheight=0, bwidth=0;
158 layout.get_pixel_size(out bwidth, out bheight);
160 if(bwidth >=(album_size-50)) {
161 ct.move_to(25, aheight+25+5);
162 p = new Cairo.Pattern.linear(0, 0, album_size-25,0);
163 p.add_color_stop_rgba(0, 1,1,1,1);
164 p.add_color_stop_rgba((album_size-50)/(double)(album_size), 1,1,1,1);
165 p.add_color_stop_rgba(1, 1,1,1,0.0);
166 ct.set_source(p);
167 }else {
168 ct.move_to(album_size-25-bwidth, aheight+25+5);
169 ct.set_source_rgb(1,1,1);
171 Pango.cairo_layout_path(ct,layout);
172 ct.fill();
176 /* We get blocks of image data,
177 * Do manual memory management because
178 * vala cannot do this?
180 void *data = null;
181 uint len = 0;
182 surf.write_to_png_stream((imgdata)=>
184 data = GLib.realloc(data, len+imgdata.length);
185 GLib.Memory.copy(&data[len], imgdata, imgdata.length);
186 len += imgdata.length;
187 return Cairo.Status.SUCCESS;
189 /* Create result message */
190 MetaData.Item pitem = new MetaData.Item();
191 pitem.type = Gmpc.MetaData.Type.ALBUM_ART;
192 pitem.plugin_name = get_name();
193 pitem.content_type = MetaData.ContentType.RAW;
194 /* This function will take over the data and set data=null
195 * len = 0
197 pitem.set_raw_void(ref data,ref len);
198 /* this isn't needed as set_raw_void takes ownershit */
199 GLib.free(data);
200 List<MetaData.Item> list = null;
201 list.append((owned)pitem);
202 callback((owned)list);