Skip to content

Commit

Permalink
Preliminary version of image resizing
Browse files Browse the repository at this point in the history
Images get resized if the message doesn't fit into the limit (300 kB
by default). Requires ImageMagick. Works on images taken by camera.

Dies and brings the whole system down on large images. We should be
able to resize images (at least JPEGs) without loading the whole thing
into the memory...
  • Loading branch information
monich committed Feb 27, 2014
1 parent f6be8fc commit 6fc062d
Show file tree
Hide file tree
Showing 14 changed files with 412 additions and 47 deletions.
2 changes: 1 addition & 1 deletion mms-engine/Makefile
Expand Up @@ -7,7 +7,7 @@

# Required packages
PKGS = gio-unix-2.0 gio-2.0 glib-2.0
LIB_PKGS = libwspcodec libsoup-2.4 $(PKGS)
LIB_PKGS = libwspcodec libsoup-2.4 ImageMagick $(PKGS)

#
# Default target
Expand Down
13 changes: 11 additions & 2 deletions mms-engine/main.c
Expand Up @@ -149,6 +149,7 @@ mms_app_parse_options(
gboolean ok;
GError* error = NULL;
gboolean session_bus = FALSE;
gint size_limit_kb = opt->config.size_limit/1024;
char* root_dir_help = g_strdup_printf(
"Root directory for MMS files [%s]",
opt->config.root_dir);
Expand All @@ -158,6 +159,9 @@ mms_app_parse_options(
char* idle_secs_help = g_strdup_printf(
"Inactivity timeout in seconds [%d]",
opt->config.idle_secs);
char* size_limit_help = g_strdup_printf(
"Maximum size for outgoing messages [%d]",
size_limit_kb);
char* description = mms_log_description(mms_app_log_modules,
G_N_ELEMENTS(mms_app_log_modules));

Expand All @@ -171,6 +175,8 @@ mms_app_parse_options(
&opt->config.retry_secs, retry_secs_help, "SEC" },
{ "idle-secs", 'i', 0, G_OPTION_ARG_INT,
&opt->config.idle_secs, idle_secs_help, "SEC" },
{ "size-limit", 's', 0, G_OPTION_ARG_INT,
&size_limit_kb, size_limit_help, "KB" },
{ "keep-running", 'k', 0, G_OPTION_ARG_NONE, &opt->keep_running,
"Keep running after everything is done", NULL },
{ "keep-temp-files", 't', 0, G_OPTION_ARG_NONE,
Expand All @@ -197,10 +203,12 @@ mms_app_parse_options(
g_free(root_dir_help);
g_free(retry_secs_help);
g_free(idle_secs_help);
g_free(size_limit_help);
g_free(description);

if (ok) {
if (ok && size_limit_kb >= 0) {
MMS_INFO("Starting");
opt->config.size_limit = size_limit_kb * 1024;
if (opt->dir) opt->config.root_dir = opt->dir;
if (session_bus) {
MMS_DEBUG("Attaching to session bus");
Expand All @@ -221,7 +229,7 @@ int main(int argc, char* argv[])
{
int result = 1;
MMSAppOptions opt = {0};
mms_lib_init();
mms_lib_init(argv[0]);
mms_log_default.name = MMS_APP_LOG_PREFIX;
mms_lib_default_config(&opt.config);
if (mms_app_parse_options(&opt, argc, argv)) {
Expand Down Expand Up @@ -260,5 +268,6 @@ int main(int argc, char* argv[])
closelog();
}
g_free(opt.dir);
mms_lib_deinit();
return result;
}
2 changes: 1 addition & 1 deletion mms-engine/mms-engine.pro
@@ -1,7 +1,7 @@
TEMPLATE = app
CONFIG -= qt
CONFIG += link_pkgconfig
PKGCONFIG += libsoup-2.4 gio-unix-2.0 gio-2.0 glib-2.0 dbus-1 libwspcodec
PKGCONFIG += gio-unix-2.0 gio-2.0 glib-2.0 libsoup-2.4 libwspcodec ImageMagick
DBUS_INTERFACE_DIR = $$_PRO_FILE_PWD_
MMS_LIB_DIR = $$_PRO_FILE_PWD_/../mms-lib
MMS_OFONO_DIR = $$_PRO_FILE_PWD_/../mms-ofono
Expand Down
18 changes: 13 additions & 5 deletions mms-lib/Makefile
Expand Up @@ -15,10 +15,10 @@ all: debug release
# Sources
#

SRC = mms_attachment.c mms_codec.c mms_connection.c mms_connman.c \
mms_dispatcher.c mms_error.c mms_handler.c mms_lib_util.c mms_file_util.c \
mms_log.c mms_message.c mms_task.c mms_task_ack.c mms_task_decode.c \
mms_task_encode.c mms_task_http.c mms_task_notification.c \
SRC = mms_attachment.c mms_attachment_image.c mms_codec.c mms_connection.c \
mms_connman.c mms_dispatcher.c mms_error.c mms_handler.c mms_lib_util.c \
mms_file_util.c mms_log.c mms_message.c mms_task.c mms_task_ack.c \
mms_task_decode.c mms_task_encode.c mms_task_http.c mms_task_notification.c \
mms_task_notifyresp.c mms_task_publish.c mms_task_read.c \
mms_task_retrieve.c mms_task_send.c mms_util.c

Expand All @@ -44,6 +44,13 @@ ifneq ($(GCOV),0)
CFLAGS += --coverage
endif

#
# ImageMagick support
#

DEFINES += -DHAVE_IMAGEMAGICK
PKGS += ImageMagick

#
# Tools and flags
#
Expand All @@ -57,7 +64,8 @@ DEBUG_DEFS = -DDEBUG
RELEASE_DEFS =
WARNINGS = -Wall
INCLUDES = -I$(SRC_DIR) -I$(INCLUDE_DIR)
CFLAGS += $(WARNINGS) $(INCLUDES) $(shell pkg-config --cflags $(PKGS)) -MMD
CFLAGS += $(WARNINGS) $(DEFINES) $(INCLUDES) \
$(shell pkg-config --cflags $(PKGS)) -MMD

ifndef KEEP_SYMBOLS
KEEP_SYMBOLS = 0
Expand Down
1 change: 1 addition & 0 deletions mms-lib/include/mms_lib_types.h
Expand Up @@ -49,6 +49,7 @@ typedef struct mms_config {
const char* user_agent; /* User agent string */
int retry_secs; /* Retry timeout in seconds */
int idle_secs; /* Idle timeout */
gsize size_limit; /* Maximum size of m-Send.req PDU */
gboolean keep_temp_files; /* Keep temporary files around */
gboolean attic_enabled; /* Keep unrecognized push message in attic */
gboolean send_dr; /* Allow sending delivery reports */
Expand Down
7 changes: 6 additions & 1 deletion mms-lib/include/mms_lib_util.h
Expand Up @@ -32,7 +32,12 @@ typedef enum {

/* One-time initialization */
void
mms_lib_init(void);
mms_lib_init(
const char* path);

/* Final deinitialization */
void
mms_lib_deinit(void);

/* Reset configuration to default */
void
Expand Down
4 changes: 4 additions & 0 deletions mms-lib/mms-lib.pro
Expand Up @@ -6,6 +6,9 @@ PKGCONFIG += glib-2.0 libsoup-2.4 libwspcodec
INCLUDEPATH += include
QMAKE_CFLAGS += -Wno-unused

DEFINES += HAVE_IMAGEMAGICK
PKGCONFIG += ImageMagick

CONFIG(debug, debug|release) {
DEFINES += DEBUG
DESTDIR = $$_PRO_FILE_PWD_/build/debug
Expand All @@ -15,6 +18,7 @@ CONFIG(debug, debug|release) {

SOURCES += \
src/mms_attachment.c \
src/mms_attachment_image.c \
src/mms_codec.c \
src/mms_connection.c \
src/mms_connman.c \
Expand Down
79 changes: 55 additions & 24 deletions mms-lib/src/mms_attachment.c
Expand Up @@ -53,12 +53,12 @@ mms_attachment_finalize(
g_mapped_file_unref(at->map);
if (!at->config->keep_temp_files &&
!(at->flags & MMS_ATTACHMENT_DONT_DELETE_FILES)) {
char* dir = g_path_get_dirname(at->file_name);
remove(at->file_name);
char* dir = g_path_get_dirname(at->original_file);
remove(at->original_file);
rmdir(dir);
g_free(dir);
}
g_free(at->file_name);
g_free(at->original_file);
g_free(at->content_type);
g_free(at->content_location);
g_free(at->content_id);
Expand Down Expand Up @@ -208,26 +208,25 @@ mms_attachment_new(
if (path) {
GMappedFile* map = g_mapped_file_new(path, FALSE, error);
if (map) {
MMSAttachment* at = g_object_new(MMS_TYPE_ATTACHMENT, NULL);
at->config = config;
at->file_name = path;
at->map = map;
unsigned int flags = 0;
char* content_type = NULL;
MMSAttachment* at;

if (info->content_type) {
char** ct = mms_parse_http_content_type(info->content_type);
if (ct) {
at->content_type = mms_unparse_http_content_type(ct);
content_type = mms_unparse_http_content_type(ct);
if (!strcmp(ct[0], SMIL_CONTENT_TYPE)) {
at->flags |= MMS_ATTACHMENT_SMIL;
flags |= MMS_ATTACHMENT_SMIL;
}
g_strfreev(ct);
}
}

if (!at->content_type) {
if (!content_type) {
/* Use magic to determine mime type */
const char* default_charset = "utf-8";
const char* content_type = NULL;
const char* detected_type = NULL;
const char* charset = NULL;
const char* ct[4];
int n;
Expand All @@ -236,50 +235,57 @@ mms_attachment_new(
magic_t magic = magic_open(MAGIC_MIME_TYPE);
if (magic) {
if (magic_load(magic, NULL) == 0) {
content_type = magic_file(magic, path);
detected_type = magic_file(magic, path);
}
}

/* Magic detects SMIL as text/html */
if ((!content_type ||
g_str_has_prefix(content_type, "text/")) &&
if ((!detected_type ||
g_str_has_prefix(detected_type, "text/")) &&
mms_file_is_smil(path)) {
content_type = SMIL_CONTENT_TYPE;
detected_type = SMIL_CONTENT_TYPE;
}
#endif

if (!content_type) {
if (!detected_type) {
MMS_WARN("No mime type for %s", path);
content_type = MMS_ATTACHMENT_DEFAULT_TYPE;
detected_type = MMS_ATTACHMENT_DEFAULT_TYPE;
}

if (!strcmp(content_type, SMIL_CONTENT_TYPE)) {
at->flags |= MMS_ATTACHMENT_SMIL;
if (!strcmp(detected_type, SMIL_CONTENT_TYPE)) {
flags |= MMS_ATTACHMENT_SMIL;
charset = default_charset;
} else if (g_str_has_prefix(content_type, "text/")) {
} else if (g_str_has_prefix(detected_type, "text/")) {
charset = default_charset;
}

n = 0;
ct[n++] = content_type;
ct[n++] = detected_type;
if (charset) {
ct[n++] = "charset";
ct[n++] = charset;
}
ct[n++] = NULL;
at->content_type = mms_unparse_http_content_type((char**)ct);
content_type = mms_unparse_http_content_type((char**)ct);

#ifdef HAVE_MAGIC
if (magic) magic_close(magic);
#endif
}

MMS_DEBUG("%s: %s", path, content_type);
at = g_object_new(g_str_has_prefix(content_type, "image/") ?
MMS_TYPE_ATTACHMENT_IMAGE : MMS_TYPE_ATTACHMENT, NULL);

at->config = config;
at->map = map;
at->flags |= flags;
at->file_name = at->original_file = path;
at->content_type = content_type;
at->content_location = g_path_get_basename(path);
at->content_id = (info->content_id && info->content_id[0]) ?
g_strdup(info->content_id) :
g_strdup(at->content_location);

MMS_DEBUG("%s: %s", path, at->content_type);
return at;
}
g_free(path);
Expand All @@ -302,6 +308,31 @@ mms_attachment_unref(
if (at) g_object_unref(MMS_ATTACHMENT(at));
}

void
mms_attachment_reset(
MMSAttachment* at)
{
if (at) {
MMSAttachmentClass* klass = MMS_ATTACHMENT_GET_CLASS(at);
if (klass->fn_reset) {
klass->fn_reset(at);
}
}
}

gboolean
mms_attachment_resize(
MMSAttachment* at)
{
if (at) {
MMSAttachmentClass* klass = MMS_ATTACHMENT_GET_CLASS(at);
if (klass->fn_resize) {
return klass->fn_resize(at);
}
}
return FALSE;
}

/*
* Local Variables:
* mode: C
Expand Down
16 changes: 15 additions & 1 deletion mms-lib/src/mms_attachment.h
Expand Up @@ -21,7 +21,8 @@
struct _mms_attachment {
GObject parent; /* Parent object */
const MMSConfig* config; /* Immutable configuration */
char* file_name; /* Full path name */
char* original_file; /* Full path to the original file */
const char* file_name; /* Actual file name */
char* content_type; /* Content type */
char* content_id; /* Content id */
char* content_location; /* Content location */
Expand All @@ -30,15 +31,20 @@ struct _mms_attachment {

#define MMS_ATTACHMENT_SMIL (0x01)
#define MMS_ATTACHMENT_DONT_DELETE_FILES (0x02)
#define MMS_ATTACHMENT_RESIZABLE (0x04)

};

typedef struct mms_attachment_class {
GObjectClass parent;
void (*fn_reset)(MMSAttachment* attachment);
gboolean (*fn_resize)(MMSAttachment* attachment);
} MMSAttachmentClass;

GType mms_attachment_get_type(void);
GType mms_attachment_image_get_type(void);
#define MMS_TYPE_ATTACHMENT (mms_attachment_get_type())
#define MMS_TYPE_ATTACHMENT_IMAGE (mms_attachment_image_get_type())
#define MMS_ATTACHMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
MMS_TYPE_ATTACHMENT, MMSAttachmentClass))

Expand All @@ -64,6 +70,14 @@ void
mms_attachment_unref(
MMSAttachment* attachment);

void
mms_attachment_reset(
MMSAttachment* attachment);

gboolean
mms_attachment_resize(
MMSAttachment* attachment);

#endif /* JOLLA_MMS_ATTACHMENT_H */

/*
Expand Down

0 comments on commit 6fc062d

Please sign in to comment.