A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 192 lines 5.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * load image decoder. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21 22#include "plugin.h" 23#include "imageviewer.h" 24#include "image_decoder.h" 25 26static const char *decoder_names[MAX_IMAGE_TYPES] = { 27 "bmp", 28 "jpeg", // Default decoder for jpeg: Use jpeg for old decoder, jpegp for new 29 "png", 30#ifdef HAVE_LCD_COLOR 31 "ppm", 32#endif 33 "gif", 34 "jpegp", 35}; 36 37/* Check file type by magic number or file extension 38 * 39 * If the file contains magic number, use it to determine image type. 40 * Otherwise use file extension to determine image type. 41 * If the file contains magic number and file extension is not correct, 42 * informs user that something is wrong. 43 */ 44enum image_type get_image_type(const char *name, bool quiet) 45{ 46 static const struct { 47 char *ext; 48 enum image_type type; 49 } ext_list[] = { 50 { ".bmp", IMAGE_BMP }, 51 { ".jpg", IMAGE_JPEG }, 52 { ".jpe", IMAGE_JPEG }, 53 { ".jpeg", IMAGE_JPEG }, 54 { ".png", IMAGE_PNG }, 55#ifdef HAVE_LCD_COLOR 56 { ".ppm", IMAGE_PPM }, 57#endif 58 { ".gif", IMAGE_GIF }, 59 }; 60 static const struct { 61 char *magic; /* magic number */ 62 int length; /* length of the magic number */ 63 enum image_type type; 64 } magic_list[] = { 65 { "BM", 2, IMAGE_BMP }, 66 { "\xff\xd8\xff\xe0", 4, IMAGE_JPEG }, 67 { "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8, IMAGE_PNG }, 68#ifdef HAVE_LCD_COLOR 69 { "P3", 2, IMAGE_PPM }, 70 { "P6", 2, IMAGE_PPM }, 71#endif 72 { "GIF87a", 6, IMAGE_GIF }, 73 { "GIF89a", 6, IMAGE_GIF }, 74 }; 75 76 enum image_type type = IMAGE_UNKNOWN; 77 const char *ext = rb->strrchr(name, '.'); 78 int i, fd; 79 char buf[12]; 80 81 /* check file extention */ 82 if (ext) 83 { 84 for (i = 0; i < (int)ARRAYLEN(ext_list); i++) 85 { 86 if (!rb->strcasecmp(ext, ext_list[i].ext)) 87 { 88 type = ext_list[i].type; 89 break; 90 } 91 } 92 } 93 94 /* check magic value in the file */ 95 fd = rb->open(name, O_RDONLY); 96 if (fd >= 0) 97 { 98 rb->memset(buf, 0, sizeof buf); 99 rb->read(fd, buf, sizeof buf); 100 rb->close(fd); 101 for (i = 0; i < (int)ARRAYLEN(magic_list); i++) 102 { 103 if (!rb->memcmp(buf, magic_list[i].magic, magic_list[i].length)) 104 { 105 if (!quiet && type != magic_list[i].type) 106 { 107 /* file extension is wrong. */ 108 rb->splashf(HZ*1, "Note: File extension is not correct"); 109 } 110 type = magic_list[i].type; 111 break; 112 } 113 } 114 } 115 return type; 116} 117 118static void *decoder_handle = NULL; 119const struct image_decoder *load_decoder(struct loader_info *loader_info) 120{ 121 const char *name; 122 char filename[MAX_PATH]; 123 struct imgdec_header *hdr; 124 struct lc_header *lc_hdr; 125 126 if (loader_info->type < 0 || loader_info->type >= MAX_IMAGE_TYPES) 127 { 128 rb->splashf(2*HZ, "Unknown type: %d", loader_info->type); 129 goto error; 130 } 131 132 release_decoder(); 133 134 name = decoder_names[loader_info->type]; 135 rb->snprintf(filename, MAX_PATH, VIEWERS_DIR "/%s.ovl", name); 136 137 /* load decoder to the buffer. */ 138 decoder_handle = rb->lc_open(filename, loader_info->buffer, loader_info->size); 139 if (!decoder_handle) 140 { 141 rb->splashf(2*HZ, "Can't open %s", filename); 142 goto error; 143 } 144 145 hdr = rb->lc_get_header(decoder_handle); 146 if (!hdr) 147 { 148 rb->splash(2*HZ, "Can't get header"); 149 goto error_close; 150 } 151 lc_hdr = &hdr->lc_hdr; 152 153 if (lc_hdr->magic != PLUGIN_MAGIC || lc_hdr->target_id != TARGET_ID) 154 { 155 rb->splashf(2*HZ, "%s decoder: Incompatible model.", name); 156 goto error_close; 157 } 158 159 if (lc_hdr->api_version != IMGDEC_API_VERSION || 160 hdr->img_api_size > sizeof(struct imgdec_api) || 161 hdr->plugin_api_version != PLUGIN_API_VERSION || 162 hdr->plugin_api_size > sizeof(struct plugin_api)) 163 { 164 rb->splashf(2*HZ, "%s decoder: Incompatible version.", name); 165 goto error_close; 166 } 167 168 *(hdr->api) = rb; 169 *(hdr->img_api) = loader_info->iv; 170 171 /* set remaining buffer size to loader_info. decoder will 172 * be loaded to the end of the buffer, so fix size only. */ 173#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 174 loader_info->size = lc_hdr->load_addr - loader_info->buffer; 175#endif 176 177 return hdr->decoder; 178 179error_close: 180 release_decoder(); 181error: 182 return NULL; 183} 184 185void release_decoder(void) 186{ 187 if (decoder_handle != NULL) 188 { 189 rb->lc_close(decoder_handle); 190 decoder_handle = NULL; 191 } 192}