Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c (révision 15556) +++ apps/gui/gwps-common.c (copie de travail) @@ -48,6 +48,7 @@ /* Image stuff */ #include "bmp.h" #include "atoi.h" +#include "albumart.h" #endif #include "dsp.h" #include "action.h" @@ -929,6 +930,19 @@ case WPS_TOKEN_METADATA_COMMENT: return id3->comment; +#ifdef HAVE_LCD_BITMAP + case WPS_TOKEN_ALBUMART_DISPLAY: + draw_album_art(gwps, audio_current_aa_hid()); + return NULL; + + case WPS_TOKEN_ALBUMART_FOUND: + if (audio_current_aa_hid() >= 0) { + snprintf(buf, buf_size, "C"); + return buf; + } + return NULL; +#endif + case WPS_TOKEN_FILE_BITRATE: if(id3->bitrate) snprintf(buf, buf_size, "%d", id3->bitrate); Index: apps/gui/albumart.c =================================================================== --- apps/gui/albumart.c (révision 0) +++ apps/gui/albumart.c (révision 0) @@ -0,0 +1,228 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Nicolas Pennequin + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include "sprintf.h" +#include "system.h" +#include "albumart.h" +#include "id3.h" +#include "gwps.h" +#include "buffering.h" +#include "dircache.h" +#include "debug.h" + + +/* Strip filename from a full path + * + * buf - buffer to extract directory to. + * buf_size - size of buffer. + * fullpath - fullpath to extract from. + * + * Split the directory part of the given fullpath and store it in buf + * (including last '/'). + * The function return parameter is a pointer to the filename + * inside the given fullpath. + */ +static char* strip_filename(char* buf, int buf_size, const char* fullpath) +{ + char* sep; + int len; + + if (!buf || buf_size <= 0 || !fullpath) + return NULL; + + /* if 'fullpath' is only a filename return immediately */ + sep = strrchr(fullpath, '/'); + if (sep == NULL) + { + buf[0] = 0; + return (char*)fullpath; + } + + len = MIN(sep - fullpath + 1, buf_size - 1); + strncpy(buf, fullpath, len); + buf[len] = 0; + return (sep + 1); +} + +static char* strip_extension(char* buf, int buf_size, const char* file) +{ + char* sep; + int len; + + if (!buf || buf_size <= 0 || !file) + return NULL; + + buf[0] = 0; + + sep = strrchr(file,'.'); + if (sep == NULL) + return NULL; + + len = MIN(sep - file, buf_size - 1); + strncpy(buf, file, len); + buf[len] = 0; + return buf; +} + +static bool file_exists(const char *file) +{ + int fd; + + if (!file || strlen(file) <= 0) + return false; + +#ifdef HAVE_DIRCACHE + if (dircache_is_enabled()) + return (dircache_get_entry_ptr(file) != NULL); +#endif + + fd = open(file, O_RDONLY); + if (fd < 0) + return false; + close(fd); + return true; +} + +/* Look for albumart bitmap in the same dir as the track and in its parent dir; + * stores the found filename in the track->albumart_path. + * Returns true if a bitmap was found, false otherwise */ +bool find_albumart(const struct mp3entry *id3, char *buf, int buflen) +{ + char path[MAX_PATH + 1]; + char dir[MAX_PATH + 1]; + bool found = false; + const char *trackname; + + if (!id3 || !buf) + return false; + + trackname = id3->path; + strip_filename(dir, sizeof(dir), trackname); + + DEBUGF("Looking for album art for %s\n", trackname); + + /* the first file we look for is one specific to the track playing */ + strip_extension(path, sizeof(path) - 4, trackname); + strcat(path, ".bmp"); + found = file_exists(path); + if (!found && id3->album && strlen(id3->album) > 0) + { /* if it doesn't exist, + * we look for a file specific to the track's album name */ + snprintf(path, sizeof(path) - 1, + "%s%s.bmp", + (strlen(dir) >= 1) ? dir : "", + id3->album); + path[sizeof(path) - 1] = 0; + found = file_exists(path); + } + + if (!found) + { + /* if it still doesn't exist, we look for a generic file */ + snprintf(path, sizeof(path)-1, + "%scover.bmp", + (strlen(dir) >= 1) ? dir : ""); + path[sizeof(path)-1] = 0; + found = file_exists(path); + } + + if (!found) + { + /* if it still doesn't exist, + * we continue to search in the parent directory */ + char temp[MAX_PATH + 1]; + strncpy(temp, dir, strlen(dir) - 1); + temp[strlen(dir) - 1] = 0; + + strip_filename(dir, sizeof(dir), temp); + } + + if (!found && id3->album && strlen(id3->album) > 0) + { + /* we look in the parent directory + ** for a file specific to the track's album name */ + snprintf(path, sizeof(path)-1, + "%s%s.bmp", + (strlen(dir) >= 1) ? dir : "", + id3->album); + found = file_exists(path); + } + + if (!found) + { + /* if it still doesn't exist, we look in the parent directory + * for a generic file */ + snprintf(path, sizeof(path)-1, + "%scover.bmp", + (strlen(dir) >= 1) ? dir : ""); + path[sizeof(path)-1] = 0; + found = file_exists(path); + } + + if (!found) + return false; + + strncpy(buf, path, buflen); + DEBUGF("Album art found for %s : %s\n", trackname, path); + return true; +} + +void draw_album_art(struct gui_wps *gwps, int handle_id) +{ + if(!gwps || !gwps->data || !gwps->display || handle_id < 0) + return; + + struct wps_data *data = gwps->data; + /* if(data->wps_uses_albumart == WPS_ALBUMART_NONE) + return; */ + + struct bitmap *bmp; + bufgetdata(handle_id, 0, (void *)&bmp); + + short x = data->albumart_x; + short y = data->albumart_y; + short width = bmp->width; + short height = bmp->height; + + if(data->albumart_max_width > 0) + { + width = MIN(bmp->width, data->albumart_max_width); + + if (data->albumart_xalign & WPS_ALBUMART_ALIGN_RIGHT) + x += data->albumart_max_width - width; + else if (data->albumart_xalign & WPS_ALBUMART_ALIGN_CENTER) + x += (data->albumart_max_width - width)/2; + } + + if(data->albumart_max_height > 0) + { + height = MIN(bmp->height, data->albumart_max_height); + + if (data->albumart_yalign & WPS_ALBUMART_ALIGN_BOTTOM) + y += data->albumart_max_height - height; + else if (data->albumart_yalign & WPS_ALBUMART_ALIGN_CENTER) + y += (data->albumart_max_height - height)/2; + } + + gwps->display->set_drawmode(DRMODE_FG); + gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, bmp->width, + x, y, width, height); + gwps->display->set_drawmode(DRMODE_SOLID); +} Index: apps/gui/albumart.h =================================================================== --- apps/gui/albumart.h (révision 0) +++ apps/gui/albumart.h (révision 0) @@ -0,0 +1,35 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Nicolas Pennequin + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _ALBUMART_H_ +#define _ALBUMART_H_ + +#ifdef HAVE_LCD_BITMAP + +#include +#include "id3.h" +#include "gwps.h" + + +bool find_albumart(const struct mp3entry *id3, char *buf, int buflen); +void draw_album_art(struct gui_wps *gwps, int handle_id); + +#endif /* HAVE_LCD_BITMAP */ + +#endif /* _ALBUMART_H_ */ Index: apps/gui/gwps.c =================================================================== --- apps/gui/gwps.c (révision 15556) +++ apps/gui/gwps.c (copie de travail) @@ -796,3 +796,18 @@ unload_remote_wps_backdrop(); #endif } + +/* + * returns true if at least one of the gui_wps screens + * has an albumart tag in its wps structure + */ +bool gui_sync_wps_uses_albumart(void) +{ + int i; + FOR_NB_SCREENS(i) { + struct gui_wps *gwps = &gui_wps[i]; + if (gwps->data && (gwps->data->wps_uses_albumart != WPS_ALBUMART_NONE)) + return true; + } + return false; +} Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (révision 15556) +++ apps/gui/wps_parser.c (copie de travail) @@ -124,6 +124,10 @@ struct wps_token *token, struct wps_data *wps_data); static int parse_image_load(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); +static int parse_albumart_load(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); +static int parse_albumart_conditional(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); #endif /*HAVE_LCD_BITMAP */ #ifdef CONFIG_RTC @@ -283,6 +287,8 @@ { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, + { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load }, + { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_DYNAMIC, parse_albumart_conditional }, #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, #endif @@ -606,6 +612,217 @@ #endif } +#ifdef HAVE_LCD_BITMAP +static int parse_albumart_load(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + const char* _pos; + bool parsing; + const short xalign_mask = WPS_ALBUMART_ALIGN_LEFT | + WPS_ALBUMART_ALIGN_CENTER | + WPS_ALBUMART_ALIGN_RIGHT; + const short yalign_mask = WPS_ALBUMART_ALIGN_TOP | + WPS_ALBUMART_ALIGN_CENTER | + WPS_ALBUMART_ALIGN_BOTTOM; + + (void)(token); /* silence warning */ + + /* reset albumart info in wps */ + wps_data->wps_uses_albumart = WPS_ALBUMART_NONE; + wps_data->albumart_max_width = -1; + wps_data->albumart_max_height = -1; + wps_data->albumart_xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */ + wps_data->albumart_yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */ + + /* format: %Cl|x|y|[[l|c|r][d|i|s]mwidth]|[[t|c|b][d|i|s]mheight]| */ + /* initial validation and parsing of x and y components */ + if (*wps_bufptr != '|') + return 0; /* malformed token: e.g. %Cl7 */ + + _pos = wps_bufptr+1; + if (!isdigit(*_pos)) + return 0; /* malformed token: e.g. %Cl|@ */ + wps_data->albumart_x = atoi(_pos); + + _pos = strchr(_pos, '|'); + if (!_pos || !isdigit(*(++_pos))) + return 0; /* malformed token: e.g. %Cl|7\n or %Cl|7|@ */ + + wps_data->albumart_y = atoi(_pos); + + _pos = strchr(_pos, '|'); + if (!_pos) + return 0; /* malformed token: no | after y coordinate + e.g. %Cl|7|59\n */ + + /* parsing width field */ + parsing = true; + while (parsing) + { + /* apply each modifier in turn */ + ++_pos; + switch (*_pos) + { + case 'l': + case 'L': + case '+': + wps_data->albumart_xalign = + (wps_data->albumart_xalign & xalign_mask) | + WPS_ALBUMART_ALIGN_LEFT; + break; + case 'c': + case 'C': + wps_data->albumart_xalign = + (wps_data->albumart_xalign & xalign_mask) | + WPS_ALBUMART_ALIGN_CENTER; + break; + case 'r': + case 'R': + case '-': + wps_data->albumart_xalign = + (wps_data->albumart_xalign & xalign_mask) | + WPS_ALBUMART_ALIGN_RIGHT; + break; + case 'd': + case 'D': + wps_data->albumart_xalign |= WPS_ALBUMART_DECREASE; + break; + case 'i': + case 'I': + wps_data->albumart_xalign |= WPS_ALBUMART_INCREASE; + break; + case 's': + case 'S': + wps_data->albumart_xalign |= + (WPS_ALBUMART_DECREASE | WPS_ALBUMART_INCREASE); + break; + default: + parsing = false; + break; + } + } + /* extract max width data */ + if (*_pos != '|') + { + if (!isdigit(*_pos)) + return 0; /* malformed token: e.g. %Cl|7|59|# */ + wps_data->albumart_max_width = atoi(_pos); + _pos = strchr(_pos, '|'); + if (!_pos) + return 0; /* malformed token: no | after width field + e.g. %Cl|7|59|200\n */ + } + + /* parsing height field */ + parsing = true; + while (parsing) + { + /* apply each modifier in turn */ + ++_pos; + switch (*_pos) + { + case 't': + case 'T': + case 'r': /* yuck */ + case 'R': + case '-': + wps_data->albumart_yalign = + (wps_data->albumart_yalign & yalign_mask) | + WPS_ALBUMART_ALIGN_TOP; + break; + case 'c': + case 'C': + wps_data->albumart_yalign = + (wps_data->albumart_yalign & yalign_mask) | + WPS_ALBUMART_ALIGN_CENTER; + break; + case 'b': + case 'B': + case 'l': /* yuck */ + case 'L': + case '+': + wps_data->albumart_yalign = + (wps_data->albumart_yalign & yalign_mask) | + WPS_ALBUMART_ALIGN_BOTTOM; + break; + case 'd': + case 'D': + wps_data->albumart_yalign |= WPS_ALBUMART_DECREASE; + break; + case 'i': + case 'I': + wps_data->albumart_yalign |= WPS_ALBUMART_INCREASE; + break; + case 's': + case 'S': + wps_data->albumart_yalign |= + (WPS_ALBUMART_DECREASE | WPS_ALBUMART_INCREASE); + break; + default: + parsing = false; + break; + } + } + /* extract max height data */ + if (*_pos != '|') + { + if (!isdigit(*_pos)) + return 0; /* malformed token e.g. %Cl|7|59|200|@ */ + wps_data->albumart_max_height = atoi(_pos); + _pos = strchr(_pos, '|'); + if (!_pos) + return 0; /* malformed token: no closing | + e.g. %Cl|7|59|200|200\n */ + } + + /* if we got here, we parsed everything ok .. ! */ + if (wps_data->albumart_max_width < 0) + wps_data->albumart_max_width = 0; + else if (wps_data->albumart_max_width > LCD_WIDTH) + wps_data->albumart_max_width = LCD_WIDTH; + + if (wps_data->albumart_max_height < 0) + wps_data->albumart_max_height = 0; + else if (wps_data->albumart_max_height > LCD_HEIGHT) + wps_data->albumart_max_height = LCD_HEIGHT; + + wps_data->wps_uses_albumart = WPS_ALBUMART_LOAD; + + /* Skip the rest of the line */ + return skip_end_of_line(wps_bufptr); +} + +static int parse_albumart_conditional(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + struct wps_token *prevtoken = token; + --prevtoken; + if (wps_data->num_tokens >= 1 && prevtoken->type == WPS_TOKEN_CONDITIONAL) + { + /* This %C is part of a %?C construct. + It's either %?C or %?Cn */ + token->type = WPS_TOKEN_ALBUMART_FOUND; + if (*wps_bufptr == 'n' && *(wps_bufptr+1) == '<') + { + token->next = true; + return 1; + } + else if (*wps_bufptr == '<') + { + return 0; + } + else + { + token->type = WPS_NO_TOKEN; + return 0; + } + } + else return 0; +}; +#endif /* HAVE_LCD_BITMAP */ + /* Parse a generic token from the given string. Return the length read */ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) { @@ -915,6 +1132,9 @@ bool rwps = data->remote_wps; /* remember whether the data is for a RWPS */ #endif memset(data, 0, sizeof(*data)); +#ifdef HAVE_LCD_BITMAP + data->wps_uses_albumart = WPS_ALBUMART_NONE; +#endif wps_data_init(data); #ifdef HAVE_REMOTE_LCD data->remote_wps = rwps; Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (révision 15556) +++ apps/gui/gwps.h (copie de travail) @@ -39,6 +39,19 @@ #define WPS_ALIGN_CENTER 64 #define WPS_ALIGN_LEFT 128 +/* albumart definitions */ +#define WPS_ALBUMART_NONE 0 /* WPS does not contain AA tag */ +#define WPS_ALBUMART_CHECK 1 /* WPS contains AA conditional tag */ +#define WPS_ALBUMART_LOAD 2 /* WPS contains AA tag */ + +#define WPS_ALBUMART_ALIGN_RIGHT WPS_ALIGN_RIGHT /* x align: right */ +#define WPS_ALBUMART_ALIGN_CENTER WPS_ALIGN_CENTER /* x/y align: center */ +#define WPS_ALBUMART_ALIGN_LEFT WPS_ALIGN_LEFT /* x align: left */ +#define WPS_ALBUMART_ALIGN_TOP WPS_ALIGN_RIGHT /* y align: top */ +#define WPS_ALBUMART_ALIGN_BOTTOM WPS_ALIGN_LEFT /* y align: bottom */ +#define WPS_ALBUMART_INCREASE 8 /* increase if smaller */ +#define WPS_ALBUMART_DECREASE 16 /* decrease if larger */ + /* wps_data*/ #ifdef HAVE_LCD_BITMAP @@ -185,6 +198,10 @@ WPS_TOKEN_IMAGE_PRELOAD, WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, WPS_TOKEN_IMAGE_DISPLAY, + + /* Albumart */ + WPS_TOKEN_ALBUMART_DISPLAY, + WPS_TOKEN_ALBUMART_FOUND, #endif /* Metadata */ @@ -309,6 +326,18 @@ short progress_start; short progress_end; bool peak_meter_enabled; + + /* Album art additions */ + unsigned char wps_uses_albumart; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */ + short albumart_x; + short albumart_y; + unsigned short albumart_xalign; /* WPS_ALBUMART_ALIGN_LEFT, _CENTER, _RIGHT, + + .._INCREASE, + .._DECREASE */ + unsigned short albumart_yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM, + + .._INCREASE, + .._DECREASE */ + short albumart_max_width; + short albumart_max_height; + #else /*HAVE_LCD_CHARCELLS */ unsigned short wps_progress_pat[8]; bool full_line_progressbar; @@ -417,4 +446,7 @@ void gui_sync_wps_init(void); void gui_sync_wps_screen_init(void); +/* gives back if WPS contains an albumart tag */ +bool gui_sync_wps_uses_albumart(void); + #endif Index: apps/playback.c =================================================================== --- apps/playback.c (révision 15556) +++ apps/playback.c (copie de travail) @@ -66,6 +66,7 @@ #include "icons.h" #include "peakmeter.h" #include "action.h" +#include "albumart.h" #endif #include "lang.h" #include "bookmark.h" @@ -217,6 +218,9 @@ int audio_hid; /* The ID for the track's buffer handle */ int id3_hid; /* The ID for the track's metadata handle */ int codec_hid; /* The ID for the track's codec handle */ +#ifdef HAVE_LCD_BITMAP + int aa_hid; /* The ID for the track's album art handle */ +#endif size_t filesize; /* File total length */ @@ -391,6 +395,15 @@ return false; } +#ifdef HAVE_LCD_BITMAP + if (track->aa_hid >= 0) { + if (bufclose(track->aa_hid)) + track->aa_hid = -1; + else + return false; +#endif + } + track->filesize = 0; track->taginfo_ready = false; track->event_sent = false; @@ -635,6 +648,13 @@ #endif /* HAVE_RECORDING */ +#ifdef HAVE_LCD_BITMAP +int audio_current_aa_hid(void) +{ + return CUR_TI->aa_hid; +} +#endif + struct mp3entry* audio_current_track(void) { const char *filename; @@ -2381,6 +2401,16 @@ else track_id3 = bufgetid3(tracks[track_widx].id3_hid); + +#ifdef HAVE_LCD_BITMAP + if (gui_sync_wps_uses_albumart()) + { + char aa_path[MAX_PATH]; + if (find_albumart(track_id3, aa_path, sizeof(aa_path))) + tracks[track_widx].aa_hid = bufopen(aa_path, 0, TYPE_BITMAP); + } +#endif + track_id3->elapsed = 0; enum data_type type = TYPE_PACKET_AUDIO; @@ -3285,6 +3315,9 @@ tracks[i].audio_hid = -1; tracks[i].id3_hid = -1; tracks[i].codec_hid = -1; +#ifdef HAVE_LCD_BITMAP + tracks[i].aa_hid = -1; +#endif } /* Probably safe to say */ Index: apps/SOURCES =================================================================== --- apps/SOURCES (révision 15556) +++ apps/SOURCES (copie de travail) @@ -50,6 +50,7 @@ gui/gwps-common.c #ifdef HAVE_LCD_BITMAP gui/icon.c +gui/albumart.c #endif gui/list.c gui/option_select.c Index: apps/buffering.c =================================================================== --- apps/buffering.c (révision 15556) +++ apps/buffering.c (copie de travail) @@ -48,6 +48,7 @@ #include "playback.h" #include "pcmbuf.h" #include "buffer.h" +#include "bmp.h" #ifdef SIMULATOR #define ata_disk_is_active() 1 @@ -745,7 +746,7 @@ if (h->next && h->filerem == 0 && (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET || - h->type == TYPE_IMAGE || h->type == TYPE_CODEC || + h->type == TYPE_BITMAP || h->type == TYPE_CODEC || h->type == TYPE_ATOMIC_AUDIO)) { /* metadata handle: we can move all of it */ @@ -814,7 +815,19 @@ } } +#ifdef HAVE_LCD_BITMAP +static int load_bitmap(const int fd) +{ + int rc; + struct bitmap *bmp = (struct bitmap *)&buffer[buf_widx]; + bmp->data = &buffer[buf_widx + sizeof(struct bitmap)]; + int free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx); + rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_TRANSPARENT); + return rc + (rc > 0 ? sizeof(struct bitmap) : 0); +} +#endif + /* MAIN BUFFERING API CALLS ======================== @@ -858,7 +871,6 @@ } strncpy(h->path, file, MAX_PATH); - h->filesize = size; h->filerem = size - offset; h->offset = offset; h->ridx = buf_widx; @@ -867,7 +879,23 @@ h->available = 0; h->type = type; - if (type == TYPE_CUESHEET || type == TYPE_IMAGE) { +#ifdef HAVE_LCD_BITMAP + if (type == TYPE_BITMAP) { + mutex_lock(&llist_mutex); + size = load_bitmap(fd); + if (size <= 0) + return ERR_FILE_ERROR; + h->filerem = 0; + h->available = size; + h->widx = buf_widx + size; /* safe because the data doesn't wrap */ + buf_widx += size; /* safe too */ + mutex_unlock(&llist_mutex); + } +#endif + + h->filesize = size; + + if (type == TYPE_CUESHEET) { h->fd = fd; /* Immediately start buffering those */ LOGFQUEUE("buffering >| Q_BUFFER_HANDLE"); Index: apps/buffering.h =================================================================== --- apps/buffering.h (révision 15556) +++ apps/buffering.h (copie de travail) @@ -30,7 +30,7 @@ TYPE_ATOMIC_AUDIO, TYPE_ID3, TYPE_CUESHEET, - TYPE_IMAGE, + TYPE_BITMAP, TYPE_BUFFER, TYPE_UNKNOWN, }; Index: firmware/export/audio.h =================================================================== --- firmware/export/audio.h (révision 15556) +++ firmware/export/audio.h (copie de travail) @@ -91,6 +91,9 @@ #endif /* CONFIG_CODEC == SWCODEC */ void audio_ff_rewind(long newtime); void audio_flush_and_reload_tracks(void); +#ifdef HAVE_LCD_BITMAP +int audio_current_aa_hid(void); +#endif struct mp3entry* audio_current_track(void); struct mp3entry* audio_next_track(void); bool audio_has_changed_track(void);