Explicitly set the dialog's result code for TTS / Encoder windows. Fixes an issue...
[Rockbox.git] / apps / recorder / albumart.c
blobf918e291a9d942b07a988abde20f060de4eaae36
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"
30 #include "settings.h"
33 /* Strip filename from a full path
35 * buf - buffer to extract directory to.
36 * buf_size - size of buffer.
37 * fullpath - fullpath to extract from.
39 * Split the directory part of the given fullpath and store it in buf
40 * (including last '/').
41 * The function return parameter is a pointer to the filename
42 * inside the given fullpath.
44 static char* strip_filename(char* buf, int buf_size, const char* fullpath)
46 char* sep;
47 int len;
49 if (!buf || buf_size <= 0 || !fullpath)
50 return NULL;
52 /* if 'fullpath' is only a filename return immediately */
53 sep = strrchr(fullpath, '/');
54 if (sep == NULL)
56 buf[0] = 0;
57 return (char*)fullpath;
60 len = MIN(sep - fullpath + 1, buf_size - 1);
61 strncpy(buf, fullpath, len);
62 buf[len] = 0;
63 return (sep + 1);
66 /* Make sure part of path only contain chars valid for a FAT32 long name.
67 * Double quotes are replaced with single quotes, other unsupported chars
68 * are replaced with an underscore.
70 * path - path to modify.
71 * offset - where in path to start checking.
72 * count - number of chars to check.
74 static void fix_path_part(char* path, int offset, int count)
76 static const char invalid_chars[] = "*/:<>?\\|";
77 int i;
79 path += offset;
81 for (i = 0; i <= count; i++, path++)
83 if (*path == 0)
84 return;
85 if (*path == '"')
86 *path = '\'';
87 else if (strchr(invalid_chars, *path))
88 *path = '_';
92 /* Look for the first matching album art bitmap in the following list:
93 * ./<trackname><size>.bmp
94 * ./<albumname><size>.bmp
95 * ./cover<size>.bmp
96 * ../<albumname><size>.bmp
97 * ../cover<size>.bmp
98 * ROCKBOX_DIR/albumart/<artist>-<albumname><size>.bmp
99 * <size> is the value of the size_string parameter, <trackname> and
100 * <albumname> are read from the ID3 metadata.
101 * If a matching bitmap is found, its filename is stored in buf.
102 * Return value is true if a bitmap was found, false otherwise.
104 bool search_albumart_files(const struct mp3entry *id3, const char *size_string,
105 char *buf, int buflen)
107 char path[MAX_PATH + 1];
108 char dir[MAX_PATH + 1];
109 bool found = false;
110 const char *trackname;
111 const char *artist;
112 int dirlen;
113 int albumlen;
115 if (!id3 || !buf)
116 return false;
118 trackname = id3->path;
120 if (strcmp(trackname, "No file!") == 0)
121 return false;
123 strip_filename(dir, sizeof(dir), trackname);
124 dirlen = strlen(dir);
125 albumlen = id3->album ? strlen(id3->album) : 0;
127 /* the first file we look for is one specific to the track playing */
128 strip_extension(path, sizeof(path) - strlen(size_string) - 4, trackname);
129 strcat(path, size_string);
130 strcat(path, ".bmp");
131 found = file_exists(path);
132 if (!found && albumlen > 0)
134 /* if it doesn't exist,
135 * we look for a file specific to the track's album name */
136 snprintf(path, sizeof(path),
137 "%s%s%s.bmp", dir, id3->album, size_string);
138 fix_path_part(path, dirlen, albumlen);
139 found = file_exists(path);
142 if (!found)
144 /* if it still doesn't exist, we look for a generic file */
145 snprintf(path, sizeof(path),
146 "%scover%s.bmp", dir, size_string);
147 found = file_exists(path);
150 artist = id3->albumartist != NULL ? id3->albumartist : id3->artist;
152 if (!found && artist && id3->album)
154 /* look in the albumart subdir of .rockbox */
155 snprintf(path, sizeof(path),
156 ROCKBOX_DIR "/albumart/%s-%s%s.bmp",
157 artist,
158 id3->album,
159 size_string);
160 fix_path_part(path, strlen(ROCKBOX_DIR "/albumart/"), MAX_PATH);
161 found = file_exists(path);
164 if (!found)
166 /* if it still doesn't exist,
167 * we continue to search in the parent directory */
168 strcpy(path, dir);
169 path[dirlen - 1] = 0;
170 strip_filename(dir, sizeof(dir), path);
171 dirlen = strlen(dir);
174 /* only try parent if there is one */
175 if (dirlen > 0)
177 if (!found && albumlen > 0)
179 /* we look in the parent directory
180 * for a file specific to the track's album name */
181 snprintf(path, sizeof(path),
182 "%s%s%s.bmp", dir, id3->album, size_string);
183 fix_path_part(path, dirlen, albumlen);
184 found = file_exists(path);
187 if (!found)
189 /* if it still doesn't exist, we look in the parent directory
190 * for a generic file */
191 snprintf(path, sizeof(path),
192 "%scover%s.bmp", dir, size_string);
193 found = file_exists(path);
197 if (!found)
198 return false;
200 strncpy(buf, path, buflen);
201 DEBUGF("Album art found: %s\n", path);
202 return true;
205 /* Look for albumart bitmap in the same dir as the track and in its parent dir.
206 * Stores the found filename in the buf parameter.
207 * Returns true if a bitmap was found, false otherwise */
208 bool find_albumart(const struct mp3entry *id3, char *buf, int buflen)
210 if (!id3 || !buf)
211 return false;
213 char size_string[9];
214 struct wps_data *data = gui_wps[0].data;
216 if (!data)
217 return false;
219 DEBUGF("Looking for album art for %s\n", id3->path);
221 /* Write the size string, e.g. ".100x100". */
222 snprintf(size_string, sizeof(size_string), ".%dx%d",
223 data->albumart_max_width, data->albumart_max_height);
225 /* First we look for a bitmap of the right size */
226 if (search_albumart_files(id3, size_string, buf, buflen))
227 return true;
229 /* Then we look for generic bitmaps */
230 *size_string = 0;
231 return search_albumart_files(id3, size_string, buf, buflen);
234 /* Draw the album art bitmap from the given handle ID onto the given WPS.
235 Call with clear = true to clear the bitmap instead of drawing it. */
236 void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear)
238 if (!gwps || !gwps->data || !gwps->display || handle_id < 0)
239 return;
241 struct wps_data *data = gwps->data;
243 #ifdef HAVE_REMOTE_LCD
244 /* No album art on RWPS */
245 if (data->remote_wps)
246 return;
247 #endif
249 struct bitmap *bmp;
250 if (bufgetdata(handle_id, 0, (void *)&bmp) <= 0)
251 return;
253 short x = data->albumart_x;
254 short y = data->albumart_y;
255 short width = bmp->width;
256 short height = bmp->height;
258 if (data->albumart_max_width > 0)
260 /* Crop if the bitmap is too wide */
261 width = MIN(bmp->width, data->albumart_max_width);
263 /* Align */
264 if (data->albumart_xalign & WPS_ALBUMART_ALIGN_RIGHT)
265 x += data->albumart_max_width - width;
266 else if (data->albumart_xalign & WPS_ALBUMART_ALIGN_CENTER)
267 x += (data->albumart_max_width - width) / 2;
270 if (data->albumart_max_height > 0)
272 /* Crop if the bitmap is too high */
273 height = MIN(bmp->height, data->albumart_max_height);
275 /* Align */
276 if (data->albumart_yalign & WPS_ALBUMART_ALIGN_BOTTOM)
277 y += data->albumart_max_height - height;
278 else if (data->albumart_yalign & WPS_ALBUMART_ALIGN_CENTER)
279 y += (data->albumart_max_height - height) / 2;
282 if (!clear)
284 /* Draw the bitmap */
285 gwps->display->set_drawmode(DRMODE_FG);
286 gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, bmp->width,
287 x, y, width, height);
288 gwps->display->set_drawmode(DRMODE_SOLID);
290 else
292 /* Clear the bitmap */
293 gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
294 gwps->display->fillrect(x, y, width, height);
295 gwps->display->set_drawmode(DRMODE_SOLID);