1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
26 #include "buffering.h"
31 /* Strip filename from a full path
33 * buf - buffer to extract directory to.
34 * buf_size - size of buffer.
35 * fullpath - fullpath to extract from.
37 * Split the directory part of the given fullpath and store it in buf
38 * (including last '/').
39 * The function return parameter is a pointer to the filename
40 * inside the given fullpath.
42 static char* strip_filename(char* buf
, int buf_size
, const char* fullpath
)
47 if (!buf
|| buf_size
<= 0 || !fullpath
)
50 /* if 'fullpath' is only a filename return immediately */
51 sep
= strrchr(fullpath
, '/');
55 return (char*)fullpath
;
58 len
= MIN(sep
- fullpath
+ 1, buf_size
- 1);
59 strncpy(buf
, fullpath
, len
);
64 /* Strip extension from a filename.
66 * buf - buffer to output the result to.
67 * buf_size - size of the output buffer buffer.
68 * file - filename to strip extension from.
70 * Return value is a pointer to buf, which contains the result.
72 static char* strip_extension(char* buf
, int buf_size
, const char* file
)
77 if (!buf
|| buf_size
<= 0 || !file
)
82 sep
= strrchr(file
,'.');
86 len
= MIN(sep
- file
, buf_size
- 1);
87 strncpy(buf
, file
, len
);
92 /* Test file existence, using dircache of possible */
93 static bool file_exists(const char *file
)
97 if (!file
|| strlen(file
) <= 0)
101 if (dircache_is_enabled())
102 return (dircache_get_entry_ptr(file
) != NULL
);
105 fd
= open(file
, O_RDONLY
);
112 /* Make sure part of path only contain chars valid for a FAT32 long name.
113 * Double quotes are replaced with single quotes, other unsupported chars
114 * are replaced with an underscore.
116 * path - path to modify.
117 * offset - where in path to start checking.
118 * count - number of chars to check.
120 static void fix_path_part(char* path
, int offset
, int count
)
122 static const char invalid_chars
[] = "*/:<>?\\|";
127 for (i
= 0; i
<= count
; i
++, path
++)
131 else if (strchr(invalid_chars
, *path
))
136 /* Look for the first matching album art bitmap in the following list:
137 * ./<trackname><size>.bmp
138 * ./<albumname><size>.bmp
140 * ../<albumname><size>.bmp
142 * <size> is the value of the size_string parameter, <trackname> and
143 * <albumname> are read from the ID3 metadata.
144 * If a matching bitmap is found, its filename is stored in buf.
145 * Return value is true if a bitmap was found, false otherwise.
147 static bool search_files(const struct mp3entry
*id3
, const char *size_string
,
148 char *buf
, int buflen
)
150 char path
[MAX_PATH
+ 1];
151 char dir
[MAX_PATH
+ 1];
153 const char *trackname
;
160 trackname
= id3
->path
;
161 strip_filename(dir
, sizeof(dir
), trackname
);
162 dirlen
= strlen(dir
);
163 albumlen
= id3
->album
? strlen(id3
->album
) : 0;
165 /* the first file we look for is one specific to the track playing */
166 strip_extension(path
, sizeof(path
) - strlen(size_string
) - 4, trackname
);
167 strcat(path
, size_string
);
168 strcat(path
, ".bmp");
169 found
= file_exists(path
);
170 if (!found
&& albumlen
> 0)
172 /* if it doesn't exist,
173 * we look for a file specific to the track's album name */
174 snprintf(path
, sizeof(path
),
175 "%s%s%s.bmp", dir
, id3
->album
, size_string
);
176 fix_path_part(path
, dirlen
, albumlen
);
177 found
= file_exists(path
);
182 /* if it still doesn't exist, we look for a generic file */
183 snprintf(path
, sizeof(path
),
184 "%scover%s.bmp", dir
, size_string
);
185 found
= file_exists(path
);
190 /* if it still doesn't exist,
191 * we continue to search in the parent directory */
193 path
[dirlen
- 1] = 0;
194 strip_filename(dir
, sizeof(dir
), path
);
195 dirlen
= strlen(dir
);
198 /* only try parent if there is one */
201 if (!found
&& albumlen
> 0)
203 /* we look in the parent directory
204 * for a file specific to the track's album name */
205 snprintf(path
, sizeof(path
),
206 "%s%s%s.bmp", dir
, id3
->album
, size_string
);
207 fix_path_part(path
, dirlen
, albumlen
);
208 found
= file_exists(path
);
213 /* if it still doesn't exist, we look in the parent directory
214 * for a generic file */
215 snprintf(path
, sizeof(path
),
216 "%scover%s.bmp", dir
, size_string
);
217 found
= file_exists(path
);
224 strncpy(buf
, path
, buflen
);
225 DEBUGF("Album art found: %s\n", path
);
229 /* Look for albumart bitmap in the same dir as the track and in its parent dir.
230 * Stores the found filename in the buf parameter.
231 * Returns true if a bitmap was found, false otherwise */
232 bool find_albumart(const struct mp3entry
*id3
, char *buf
, int buflen
)
238 struct wps_data
*data
= gui_wps
[0].data
;
243 DEBUGF("Looking for album art for %s\n", id3
->path
);
245 /* Write the size string, e.g. ".100x100". */
246 snprintf(size_string
, sizeof(size_string
), ".%dx%d",
247 data
->albumart_max_width
, data
->albumart_max_height
);
249 /* First we look for a bitmap of the right size */
250 if (search_files(id3
, size_string
, buf
, buflen
))
253 /* Then we look for generic bitmaps */
255 return search_files(id3
, size_string
, buf
, buflen
);
258 /* Draw the album art bitmap from the given handle ID onto the given WPS.
259 Call with clear = true to clear the bitmap instead of drawing it. */
260 void draw_album_art(struct gui_wps
*gwps
, int handle_id
, bool clear
)
262 if (!gwps
|| !gwps
->data
|| !gwps
->display
|| handle_id
< 0)
265 struct wps_data
*data
= gwps
->data
;
267 #ifdef HAVE_REMOTE_LCD
268 /* No album art on RWPS */
269 if (data
->remote_wps
)
274 if (bufgetdata(handle_id
, 0, (void *)&bmp
) <= 0)
277 short x
= data
->albumart_x
;
278 short y
= data
->albumart_y
;
279 short width
= bmp
->width
;
280 short height
= bmp
->height
;
282 if (data
->albumart_max_width
> 0)
284 /* Crop if the bitmap is too wide */
285 width
= MIN(bmp
->width
, data
->albumart_max_width
);
288 if (data
->albumart_xalign
& WPS_ALBUMART_ALIGN_RIGHT
)
289 x
+= data
->albumart_max_width
- width
;
290 else if (data
->albumart_xalign
& WPS_ALBUMART_ALIGN_CENTER
)
291 x
+= (data
->albumart_max_width
- width
) / 2;
294 if (data
->albumart_max_height
> 0)
296 /* Crop if the bitmap is too high */
297 height
= MIN(bmp
->height
, data
->albumart_max_height
);
300 if (data
->albumart_yalign
& WPS_ALBUMART_ALIGN_BOTTOM
)
301 y
+= data
->albumart_max_height
- height
;
302 else if (data
->albumart_yalign
& WPS_ALBUMART_ALIGN_CENTER
)
303 y
+= (data
->albumart_max_height
- height
) / 2;
308 /* Draw the bitmap */
309 gwps
->display
->set_drawmode(DRMODE_FG
);
310 gwps
->display
->bitmap_part((fb_data
*)bmp
->data
, 0, 0, bmp
->width
,
311 x
, y
, width
, height
);
312 gwps
->display
->set_drawmode(DRMODE_SOLID
);
316 /* Clear the bitmap */
317 gwps
->display
->set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
318 gwps
->display
->fillrect(x
, y
, width
, height
);
319 gwps
->display
->set_drawmode(DRMODE_SOLID
);