diff options
Diffstat (limited to 'apps/recorder')
-rw-r--r-- | apps/recorder/albumart.c | 285 | ||||
-rw-r--r-- | apps/recorder/albumart.h | 39 |
2 files changed, 324 insertions, 0 deletions
diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c new file mode 100644 index 0000000000..abae8c1afc --- /dev/null +++ b/apps/recorder/albumart.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Nicolas Pennequin | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
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 | |||
30 | |||
31 | /* Strip filename from a full path | ||
32 | * | ||
33 | * buf - buffer to extract directory to. | ||
34 | * buf_size - size of buffer. | ||
35 | * fullpath - fullpath to extract from. | ||
36 | * | ||
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. | ||
41 | */ | ||
42 | static char* strip_filename(char* buf, int buf_size, const char* fullpath) | ||
43 | { | ||
44 | char* sep; | ||
45 | int len; | ||
46 | |||
47 | if (!buf || buf_size <= 0 || !fullpath) | ||
48 | return NULL; | ||
49 | |||
50 | /* if 'fullpath' is only a filename return immediately */ | ||
51 | sep = strrchr(fullpath, '/'); | ||
52 | if (sep == NULL) | ||
53 | { | ||
54 | buf[0] = 0; | ||
55 | return (char*)fullpath; | ||
56 | } | ||
57 | |||
58 | len = MIN(sep - fullpath + 1, buf_size - 1); | ||
59 | strncpy(buf, fullpath, len); | ||
60 | buf[len] = 0; | ||
61 | return (sep + 1); | ||
62 | } | ||
63 | |||
64 | /* Strip extension from a filename. | ||
65 | * | ||
66 | * buf - buffer to output the result to. | ||
67 | * buf_size - size of the output buffer buffer. | ||
68 | * file - filename to strip extension from. | ||
69 | * | ||
70 | * Return value is a pointer to buf, which contains the result. | ||
71 | */ | ||
72 | static char* strip_extension(char* buf, int buf_size, const char* file) | ||
73 | { | ||
74 | char* sep; | ||
75 | int len; | ||
76 | |||
77 | if (!buf || buf_size <= 0 || !file) | ||
78 | return NULL; | ||
79 | |||
80 | buf[0] = 0; | ||
81 | |||
82 | sep = strrchr(file,'.'); | ||
83 | if (sep == NULL) | ||
84 | return NULL; | ||
85 | |||
86 | len = MIN(sep - file, buf_size - 1); | ||
87 | strncpy(buf, file, len); | ||
88 | buf[len] = 0; | ||
89 | return buf; | ||
90 | } | ||
91 | |||
92 | /* Test file existence, using dircache of possible */ | ||
93 | static bool file_exists(const char *file) | ||
94 | { | ||
95 | int fd; | ||
96 | |||
97 | if (!file || strlen(file) <= 0) | ||
98 | return false; | ||
99 | |||
100 | #ifdef HAVE_DIRCACHE | ||
101 | if (dircache_is_enabled()) | ||
102 | return (dircache_get_entry_ptr(file) != NULL); | ||
103 | #endif | ||
104 | |||
105 | fd = open(file, O_RDONLY); | ||
106 | if (fd < 0) | ||
107 | return false; | ||
108 | close(fd); | ||
109 | return true; | ||
110 | } | ||
111 | |||
112 | /* Look for the first matching album art bitmap in the following list: | ||
113 | * ./<trackname><size>.bmp | ||
114 | * ./<albumname><size>.bmp | ||
115 | * ./cover<size>.bmp | ||
116 | * ../<albumname><size>.bmp | ||
117 | * ../cover<size>.bmp | ||
118 | * <size> is the value of the size_string parameter, <trackname> and | ||
119 | * <albumname> are read from the ID3 metadata. | ||
120 | * If a matching bitmap is found, its filename is stored in buf. | ||
121 | * Return value is true if a bitmap was found, false otherwise. | ||
122 | */ | ||
123 | static bool search_files(const struct mp3entry *id3, const char *size_string, | ||
124 | char *buf, int buflen) | ||
125 | { | ||
126 | char path[MAX_PATH + 1]; | ||
127 | char dir[MAX_PATH + 1]; | ||
128 | bool found = false; | ||
129 | const char *trackname; | ||
130 | |||
131 | if (!id3 || !buf) | ||
132 | return false; | ||
133 | |||
134 | trackname = id3->path; | ||
135 | strip_filename(dir, sizeof(dir), trackname); | ||
136 | |||
137 | /* the first file we look for is one specific to the track playing */ | ||
138 | strip_extension(path, sizeof(path) - strlen(size_string) - 4, trackname); | ||
139 | strcat(path, size_string); | ||
140 | strcat(path, ".bmp"); | ||
141 | found = file_exists(path); | ||
142 | if (!found && id3->album && strlen(id3->album) > 0) | ||
143 | { | ||
144 | /* if it doesn't exist, | ||
145 | * we look for a file specific to the track's album name */ | ||
146 | snprintf(path, sizeof(path) - 1, | ||
147 | "%s%s%s.bmp", | ||
148 | (strlen(dir) >= 1) ? dir : "", | ||
149 | id3->album, size_string); | ||
150 | path[sizeof(path) - 1] = 0; | ||
151 | found = file_exists(path); | ||
152 | } | ||
153 | |||
154 | if (!found) | ||
155 | { | ||
156 | /* if it still doesn't exist, we look for a generic file */ | ||
157 | snprintf(path, sizeof(path)-1, | ||
158 | "%scover%s.bmp", | ||
159 | (strlen(dir) >= 1) ? dir : "", size_string); | ||
160 | path[sizeof(path)-1] = 0; | ||
161 | found = file_exists(path); | ||
162 | } | ||
163 | |||
164 | if (!found) | ||
165 | { | ||
166 | /* if it still doesn't exist, | ||
167 | * we continue to search in the parent directory */ | ||
168 | char temp[MAX_PATH + 1]; | ||
169 | strncpy(temp, dir, strlen(dir) - 1); | ||
170 | temp[strlen(dir) - 1] = 0; | ||
171 | |||
172 | strip_filename(dir, sizeof(dir), temp); | ||
173 | } | ||
174 | |||
175 | if (!found && id3->album && strlen(id3->album) > 0) | ||
176 | { | ||
177 | /* we look in the parent directory | ||
178 | * for a file specific to the track's album name */ | ||
179 | snprintf(path, sizeof(path)-1, | ||
180 | "%s%s%s.bmp", | ||
181 | (strlen(dir) >= 1) ? dir : "", | ||
182 | id3->album, size_string); | ||
183 | found = file_exists(path); | ||
184 | } | ||
185 | |||
186 | if (!found) | ||
187 | { | ||
188 | /* if it still doesn't exist, we look in the parent directory | ||
189 | * for a generic file */ | ||
190 | snprintf(path, sizeof(path)-1, | ||
191 | "%scover%s.bmp", | ||
192 | (strlen(dir) >= 1) ? dir : "", size_string); | ||
193 | path[sizeof(path)-1] = 0; | ||
194 | found = file_exists(path); | ||
195 | } | ||
196 | |||
197 | if (!found) | ||
198 | return false; | ||
199 | |||
200 | strncpy(buf, path, buflen); | ||
201 | DEBUGF("Album art found: %s\n", path); | ||
202 | return true; | ||
203 | } | ||
204 | |||
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) | ||
209 | { | ||
210 | if (!id3 || !buf) | ||
211 | return false; | ||
212 | |||
213 | char size_string[9]; | ||
214 | struct wps_data *data = gui_wps[0].data; | ||
215 | |||
216 | if (!data) | ||
217 | return false; | ||
218 | |||
219 | DEBUGF("Looking for album art for %s\n", id3->path); | ||
220 | |||
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); | ||
224 | |||
225 | /* First we look for a bitmap of the right size */ | ||
226 | if (search_files(id3, size_string, buf, buflen)) | ||
227 | return true; | ||
228 | |||
229 | /* Then we look for generic bitmaps */ | ||
230 | *size_string = 0; | ||
231 | return search_files(id3, size_string, buf, buflen); | ||
232 | } | ||
233 | |||
234 | /* Draw the album art bitmap from the given handle ID onto the given WPS. */ | ||
235 | void draw_album_art(struct gui_wps *gwps, int handle_id) | ||
236 | { | ||
237 | if (!gwps || !gwps->data || !gwps->display || handle_id < 0) | ||
238 | return; | ||
239 | |||
240 | struct wps_data *data = gwps->data; | ||
241 | |||
242 | #ifdef HAVE_REMOTE_LCD | ||
243 | /* No album art on RWPS */ | ||
244 | if (data->remote_wps) | ||
245 | return; | ||
246 | #endif | ||
247 | |||
248 | struct bitmap *bmp; | ||
249 | bufgetdata(handle_id, 0, (void *)&bmp); | ||
250 | |||
251 | short x = data->albumart_x; | ||
252 | short y = data->albumart_y; | ||
253 | short width = bmp->width; | ||
254 | short height = bmp->height; | ||
255 | |||
256 | if (data->albumart_max_width > 0) | ||
257 | { | ||
258 | /* Crop if the bitmap is too wide */ | ||
259 | width = MIN(bmp->width, data->albumart_max_width); | ||
260 | |||
261 | /* Align */ | ||
262 | if (data->albumart_xalign & WPS_ALBUMART_ALIGN_RIGHT) | ||
263 | x += data->albumart_max_width - width; | ||
264 | else if (data->albumart_xalign & WPS_ALBUMART_ALIGN_CENTER) | ||
265 | x += (data->albumart_max_width - width) / 2; | ||
266 | } | ||
267 | |||
268 | if (data->albumart_max_height > 0) | ||
269 | { | ||
270 | /* Crop if the bitmap is too high */ | ||
271 | height = MIN(bmp->height, data->albumart_max_height); | ||
272 | |||
273 | /* Align */ | ||
274 | if (data->albumart_yalign & WPS_ALBUMART_ALIGN_BOTTOM) | ||
275 | y += data->albumart_max_height - height; | ||
276 | else if (data->albumart_yalign & WPS_ALBUMART_ALIGN_CENTER) | ||
277 | y += (data->albumart_max_height - height) / 2; | ||
278 | } | ||
279 | |||
280 | /* Draw the bitmap */ | ||
281 | gwps->display->set_drawmode(DRMODE_FG); | ||
282 | gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, bmp->width, | ||
283 | x, y, width, height); | ||
284 | gwps->display->set_drawmode(DRMODE_SOLID); | ||
285 | } | ||
diff --git a/apps/recorder/albumart.h b/apps/recorder/albumart.h new file mode 100644 index 0000000000..21ae50edb9 --- /dev/null +++ b/apps/recorder/albumart.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Nicolas Pennequin | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef _ALBUMART_H_ | ||
21 | #define _ALBUMART_H_ | ||
22 | |||
23 | #ifdef HAVE_ALBUMART | ||
24 | |||
25 | #include <stdbool.h> | ||
26 | #include "id3.h" | ||
27 | #include "gwps.h" | ||
28 | |||
29 | /* Look for albumart bitmap in the same dir as the track and in its parent dir. | ||
30 | * Stores the found filename in the buf parameter. | ||
31 | * Returns true if a bitmap was found, false otherwise */ | ||
32 | bool find_albumart(const struct mp3entry *id3, char *buf, int buflen); | ||
33 | |||
34 | /* Draw the album art bitmap from the given handle ID onto the given WPS. */ | ||
35 | void draw_album_art(struct gui_wps *gwps, int handle_id); | ||
36 | |||
37 | #endif /* HAVE_ALBUMART */ | ||
38 | |||
39 | #endif /* _ALBUMART_H_ */ | ||