All pastes #768393 Raw Edit

Album art

public diff v1 · immutable
#768393 ·published 2007-11-10 16:04 UTC
rendered paste body
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 <string.h>+#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 <stdbool.h>+#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<blah> or %?Cn<blah> */+        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);+ #endifIndex: 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.cIndex: 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);