From: barbieri Date: Mon, 24 Dec 2007 15:28:58 +0000 (+0000) Subject: Add PNG image support (just size) X-Git-Url: https://vcs.maemo.org/git/?p=lms;a=commitdiff_plain;h=887d3b806ea6555bf270a93d91c10e693836cdb3 Add PNG image support (just size) --- diff --git a/lightmediascanner/configure.ac b/lightmediascanner/configure.ac index 80e590c..6f0d66b 100644 --- a/lightmediascanner/configure.ac +++ b/lightmediascanner/configure.ac @@ -55,6 +55,7 @@ define([CHECK_MODULE_OGG], # plugins declarations AC_LMS_OPTIONAL_MODULE([dummy], true) AC_LMS_OPTIONAL_MODULE([jpeg], true) +AC_LMS_OPTIONAL_MODULE([png], true) AC_LMS_OPTIONAL_MODULE([id3lib], true, [CHECK_MODULE_ID3LIB]) AC_LMS_OPTIONAL_MODULE([video-dummy], true) AC_LMS_OPTIONAL_MODULE([audio-dummy], true) @@ -72,6 +73,7 @@ src/lib/Makefile src/plugins/Makefile src/plugins/dummy/Makefile src/plugins/jpeg/Makefile +src/plugins/png/Makefile src/plugins/id3lib/Makefile src/plugins/video-dummy/Makefile src/plugins/audio-dummy/Makefile diff --git a/lightmediascanner/src/plugins/Makefile.am b/lightmediascanner/src/plugins/Makefile.am index b4303cc..9f09351 100644 --- a/lightmediascanner/src/plugins/Makefile.am +++ b/lightmediascanner/src/plugins/Makefile.am @@ -10,6 +10,10 @@ if USE_MODULE_JPEG SUBDIRS += jpeg endif +if USE_MODULE_PNG +SUBDIRS += png +endif + if USE_MODULE_ID3LIB SUBDIRS += id3lib endif @@ -37,6 +41,7 @@ endif DIST_SUBDIRS = \ dummy \ jpeg \ + png \ id3lib \ video-dummy \ audio-dummy \ diff --git a/lightmediascanner/src/plugins/png/Makefile.am b/lightmediascanner/src/plugins/png/Makefile.am new file mode 100644 index 0000000..65f9a06 --- /dev/null +++ b/lightmediascanner/src/plugins/png/Makefile.am @@ -0,0 +1,10 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/png + +pkgdir = $(pluginsdir) +pkg_LTLIBRARIES = png.la +png_la_SOURCES = png.c +png_la_DEPENDENCIES = $(top_builddir)/config.h +png_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la +png_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/png/png.c b/lightmediascanner/src/plugins/png/png.c new file mode 100644 index 0000000..16b1567 --- /dev/null +++ b/lightmediascanner/src/plugins/png/png.c @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2007 by INdT + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * @author Gustavo Sverzut Barbieri + */ + +/** + * @brief + * + * Reads PNG images. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _XOPEN_SOURCE 600 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline unsigned int +_chunk_to_uint(unsigned char *buf) +{ + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +static int +_png_data_get(int fd, struct lms_image_info *info) +{ + unsigned char buf[16], *p; + const unsigned char sig[8] = {0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa}; + const unsigned char ihdr[4] = {'I', 'H', 'D', 'R'}; + unsigned int length; + + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { + perror("read"); + return -1; + } + + if (memcmp(buf, sig, sizeof(sig)) != 0) { + fprintf(stderr, "ERROR: invalid PNG signature.\n"); + return -2; + } + + p = buf + sizeof(sig) + 4; + if (memcmp(p, ihdr, sizeof(ihdr)) != 0) { + fprintf(stderr, "ERROR: invalid first chunk: %4.4s.\n", p); + return -3; + } + + p = buf + sizeof(sig); + length = _chunk_to_uint(p); + if (length < 13) { + fprintf(stderr, "ERROR: IHDR chunk size is too small: %d.\n", length); + return -4; + } + + if (read(fd, buf, 8) != 8) { + perror("read"); + return -5; + } + info->width = _chunk_to_uint(buf); + info->height = _chunk_to_uint(buf + 4); + + return 0; +} + +static const char _name[] = "png"; +static const struct lms_string_size _exts[] = { + LMS_STATIC_STRING_SIZE(".png") +}; + +struct plugin { + struct lms_plugin plugin; + lms_db_image_t *img_db; +}; + +static void * +_match(struct plugin *p, const char *path, int len, int base) +{ + int i; + + i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); + if (i < 0) + return NULL; + else + return (void*)(i + 1); +} + +static int +_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) +{ + struct lms_image_info info = {0}; + int fd, r; + + fd = open(finfo->path, O_RDONLY); + if (fd < 0) { + perror("open"); + return -1; + } + + if (_png_data_get(fd, &info) != 0) { + r = -2; + goto done; + } + + if (info.date == 0) + info.date = finfo->mtime; + + if (!info.title.str) { + int ext_idx; + + ext_idx = ((int)match) - 1; + info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; + info.title.str = malloc((info.title.len + 1) * sizeof(char)); + memcpy(info.title.str, finfo->path + finfo->base, info.title.len); + info.title.str[info.title.len] = '\0'; + } + + if (info.title.str) + lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); + if (info.artist.str) + lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); + + info.id = finfo->id; + r = lms_db_image_add(plugin->img_db, &info); + + done: + if (info.title.str) + free(info.title.str); + if (info.artist.str) + free(info.artist.str); + + posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); + close(fd); + + return r; +} + +static int +_setup(struct plugin *plugin, struct lms_context *ctxt) +{ + plugin->img_db = lms_db_image_new(ctxt->db); + if (!plugin->img_db) + return -1; + + return 0; +} + +static int +_start(struct plugin *plugin, struct lms_context *ctxt) +{ + return lms_db_image_start(plugin->img_db); +} + +static int +_finish(struct plugin *plugin, struct lms_context *ctxt) +{ + if (plugin->img_db) + return lms_db_image_free(plugin->img_db); + + return 0; +} + + +static int +_close(struct plugin *plugin) +{ + free(plugin); + return 0; +} + +API struct lms_plugin * +lms_plugin_open(void) +{ + struct plugin *plugin; + + plugin = malloc(sizeof(*plugin)); + plugin->plugin.name = _name; + plugin->plugin.match = (lms_plugin_match_fn_t)_match; + plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; + plugin->plugin.close = (lms_plugin_close_fn_t)_close; + plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; + plugin->plugin.start = (lms_plugin_start_fn_t)_start; + plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; + + return (struct lms_plugin *)plugin; +}