Ok, adding the hyphen again improves the pronounciation a bit (tested with espeak...
[Rockbox.git] / apps / recorder / albumart.c
blob6761cfc67a319f0c79a43fc6ca53a09aa72089b1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Nicolas Pennequin
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <string.h>
21 #include "sprintf.h"
22 #include "system.h"
23 #include "albumart.h"
24 #include "id3.h"
25 #include "gwps.h"
26 #include "buffering.h"
27 #include "dircache.h"
28 #include "debug.h"
29 #include "misc.h"
32 /* Strip filename from a full path
34 * buf - buffer to extract directory to.
35 * buf_size - size of buffer.
36 * fullpath - fullpath to extract from.
38 * Split the directory part of the given fullpath and store it in buf
39 * (including last '/').
40 * The function return parameter is a pointer to the filename
41 * inside the given fullpath.
43 static char* strip_filename(char* buf, int buf_size, const char* fullpath)
45 char* sep;
46 int len;
48 if (!buf || buf_size <= 0 || !fullpath)
49 return NULL;
51 /* if 'fullpath' is only a filename return immediately */
52 sep = strrchr(fullpath, '/');
53 if (sep == NULL)
55 buf[0] = 0;
56 return (char*)fullpath;
59 len = MIN(sep - fullpath + 1, buf_size - 1);
60 strncpy(buf, fullpath, len);
61 buf[len] = 0;
62 return (sep + 1);
65 /* Strip extension from a filename.
67 * buf - buffer to output the result to.
68 * buf_size - size of the output buffer buffer.
69 * file - filename to strip extension from.
71 * Return value is a pointer to buf, which contains the result.
73 static char* strip_extension(char* buf, int buf_size, const char* file)
75 char* sep;
76 int len;
78 if (!buf || buf_size <= 0 || !file)
79 return NULL;
81 buf[0] = 0;
83 sep = strrchr(file,'.');
84 if (sep == NULL)
85 return NULL;
87 len = MIN(sep - file, buf_size - 1);
88 strncpy(buf, file, len);
89 buf[len] = 0;
90 return buf;
93 /* Make sure part of path only contain chars valid for a FAT32 long name.
94 * Double quotes are replaced with single quotes, other unsupported chars
95 * are replaced with an underscore.
97 * path - path to modify.
98 * offset - where in path to start checking.
99 * count - number of chars to check.
101 static void fix_path_part(char* path, int offset, int count)
103 static const char invalid_chars[] = "*/:<>?\\|";
104 int i;
106 path += offset;
108 for (i = 0; i <= count; i++, path++)
110 if (*path == '"')
111 *path = '\'';
112 else if (strchr(invalid_chars, *path))
113 *path = '_';
117 /* Look for the first matching album art bitmap in the following list:
118 * ./<trackname><size>.bmp
119 * ./<albumname><size>.bmp
120 * ./cover<size>.bmp
121 * ../<albumname><size>.bmp
122 * ../cover<size>.bmp
123 * <size> is the value of the size_string parameter, <trackname> and
124 * <albumname> are read from the ID3 metadata.
125 * If a matching bitmap is found, its filename is stored in buf.
126 * Return value is true if a bitmap was found, false otherwise.
128 bool search_albumart_files(const struct mp3entry *id3, const char *size_string,
129 char *buf, int buflen)
131 char path[MAX_PATH + 1];
132 char dir[MAX_PATH + 1];
133 bool found = false;
134 const char *trackname;
135 int dirlen;
136 int albumlen;
138 if (!id3 || !buf)
139 return false;
141 trackname = id3->path;
142 strip_filename(dir, sizeof(dir), trackname);
143 dirlen = strlen(dir);
144 albumlen = id3->album ? strlen(id3->album) : 0;
146 /* the first file we look for is one specific to the track playing */
147 strip_extension(path, sizeof(path) - strlen(size_string) - 4, trackname);
148 strcat(path, size_string);
149 strcat(path, ".bmp");
150 found = file_exists(path);
151 if (!found && albumlen > 0)
153 /* if it doesn't exist,
154 * we look for a file specific to the track's album name */
155 snprintf(path, sizeof(path),
156 "%s%s%s.bmp", dir, id3->album, size_string);
157 fix_path_part(path, dirlen, albumlen);
158 found = file_exists(path);
161 if (!found)
163 /* if it still doesn't exist, we look for a generic file */
164 snprintf(path, sizeof(path),
165 "%scover%s.bmp", dir, size_string);
166 found = file_exists(path);
169 if (!found)
171 /* if it still doesn't exist,
172 * we continue to search in the parent directory */
173 strcpy(path, dir);
174 path[dirlen - 1] = 0;
175 strip_filename(dir, sizeof(dir), path);
176 dirlen = strlen(dir);
179 /* only try parent if there is one */
180 if (dirlen > 0)
182 if (!found && albumlen > 0)
184 /* we look in the parent directory
185 * for a file specific to the track's album name */
186 snprintf(path, sizeof(path),
187 "%s%s%s.bmp", dir, id3->album, size_string);
188 fix_path_part(path, dirlen, albumlen);
189 found = file_exists(path);
192 if (!found)
194 /* if it still doesn't exist, we look in the parent directory
195 * for a generic file */
196 snprintf(path, sizeof(path),
197 "%scover%s.bmp", dir, size_string);
198 found = file_exists(path);
202 if (!found)
203 return false;
205 strncpy(buf, path, buflen);
206 DEBUGF("Album art found: %s\n", path);
207 return true;
210 /* Look for albumart bitmap in the same dir as the track and in its parent dir.
211 * Stores the found filename in the buf parameter.
212 * Returns true if a bitmap was found, false otherwise */
213 bool find_albumart(const struct mp3entry *id3, char *buf, int buflen)
215 if (!id3 || !buf)
216 return false;
218 char size_string[9];
219 struct wps_data *data = gui_wps[0].data;
221 if (!data)
222 return false;
224 DEBUGF("Looking for album art for %s\n", id3->path);
226 /* Write the size string, e.g. ".100x100". */
227 snprintf(size_string, sizeof(size_string), ".%dx%d",
228 data->albumart_max_width, data->albumart_max_height);
230 /* First we look for a bitmap of the right size */
231 if (search_albumart_files(id3, size_string, buf, buflen))
232 return true;
234 /* Then we look for generic bitmaps */
235 *size_string = 0;
236 return search_albumart_files(id3, size_string, buf, buflen);
239 /* Draw the album art bitmap from the given handle ID onto the given WPS.
240 Call with clear = true to clear the bitmap instead of drawing it. */
241 void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear)
243 if (!gwps || !gwps->data || !gwps->display || handle_id < 0)
244 return;
246 struct wps_data *data = gwps->data;
248 #ifdef HAVE_REMOTE_LCD
249 /* No album art on RWPS */
250 if (data->remote_wps)
251 return;
252 #endif
254 struct bitmap *bmp;
255 if (bufgetdata(handle_id, 0, (void *)&bmp) <= 0)
256 return;
258 short x = data->albumart_x;
259 short y = data->albumart_y;
260 short width = bmp->width;
261 short height = bmp->height;
263 if (data->albumart_max_width > 0)
265 /* Crop if the bitmap is too wide */
266 width = MIN(bmp->width, data->albumart_max_width);
268 /* Align */
269 if (data->albumart_xalign & WPS_ALBUMART_ALIGN_RIGHT)
270 x += data->albumart_max_width - width;
271 else if (data->albumart_xalign & WPS_ALBUMART_ALIGN_CENTER)
272 x += (data->albumart_max_width - width) / 2;
275 if (data->albumart_max_height > 0)
277 /* Crop if the bitmap is too high */
278 height = MIN(bmp->height, data->albumart_max_height);
280 /* Align */
281 if (data->albumart_yalign & WPS_ALBUMART_ALIGN_BOTTOM)
282 y += data->albumart_max_height - height;
283 else if (data->albumart_yalign & WPS_ALBUMART_ALIGN_CENTER)
284 y += (data->albumart_max_height - height) / 2;
287 if (!clear)
289 /* Draw the bitmap */
290 gwps->display->set_drawmode(DRMODE_FG);
291 gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, bmp->width,
292 x, y, width, height);
293 gwps->display->set_drawmode(DRMODE_SOLID);
295 else
297 /* Clear the bitmap */
298 gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
299 gwps->display->fillrect(x, y, width, height);
300 gwps->display->set_drawmode(DRMODE_SOLID);