]> granicus.if.org Git - libass/commitdiff
Message callback funtionality
authorGrigori Goronzy <greg@blackbox>
Sat, 11 Jul 2009 00:18:51 +0000 (02:18 +0200)
committerGrigori Goronzy <greg@blackbox>
Sat, 11 Jul 2009 00:22:18 +0000 (02:22 +0200)
Introduce functionality for providing a message callback that is used
for passing messages to the controlling application instead of simply
printing them to standard output.  The function pointer to the callback
is stored in the ass_library_t instance. ass_msg needs access to it, so
in many places the library instance needs to be passed around now.

The default behavior is the old one: messages of MSGL_INFO or lower
are printed to the standard output, prefixed with "[ass]".

18 files changed:
libass/ass.c
libass/ass.h
libass/ass_bitmap.c
libass/ass_bitmap.h
libass/ass_cache.c
libass/ass_cache.h
libass/ass_drawing.c
libass/ass_drawing.h
libass/ass_font.c
libass/ass_fontconfig.c
libass/ass_fontconfig.h
libass/ass_library.c
libass/ass_library.h
libass/ass_render.c
libass/ass_utils.c
libass/ass_utils.h
libass/libass.sym
test/test.cpp

index 135232fe9ae6d9271427d53596d19ad24cd933ad..9eaa7b01d0f34dbe9cb700e72263be57f4cd2236 100644 (file)
@@ -182,26 +182,26 @@ static int lookup_style(ass_track_t *track, char *name)
             return i;
     }
     i = track->default_style;
-    ass_msg(MSGL_WARN,
+    ass_msg(track->library, MSGL_WARN,
             "[%p]: Warning: no style named '%s' found, using '%s'",
             track, name, track->styles[i].Name);
     return i;                   // use the first style
 }
 
-static uint32_t string2color(char *p)
+static uint32_t string2color(ass_library_t *library, char *p)
 {
     uint32_t tmp;
-    (void) strtocolor(&p, &tmp);
+    (void) strtocolor(library, &p, &tmp);
     return tmp;
 }
 
-static long long string2timecode(char *p)
+static long long string2timecode(ass_library_t *library, char *p)
 {
     unsigned h, m, s, ms;
     long long tm;
     int res = sscanf(p, "%1d:%2d:%2d.%2d", &h, &m, &s, &ms);
     if (res < 4) {
-        ass_msg(MSGL_WARN, "Bad timestamp");
+        ass_msg(library, MSGL_WARN, "Bad timestamp");
         return 0;
     }
     tm = ((h * 60 + m) * 60 + s) * 1000 + ms * 10;
@@ -229,22 +229,30 @@ static int numpad2align(int val)
 #define ANYVAL(name,func) \
        } else if (strcasecmp(tname, #name) == 0) { \
                target->name = func(token); \
-               ass_msg(MSGL_DBG2, "%s = %s", #name, token);
+               ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
 
 #define STRVAL(name) \
        } else if (strcasecmp(tname, #name) == 0) { \
                if (target->name != NULL) free(target->name); \
                target->name = strdup(token); \
-               ass_msg(MSGL_DBG2, "%s = %s", #name, token);
+               ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
+
+#define COLORVAL(name) \
+       } else if (strcasecmp(tname, #name) == 0) { \
+               target->name = string2color(track->library, token); \
+               ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
 
-#define COLORVAL(name) ANYVAL(name,string2color)
 #define INTVAL(name) ANYVAL(name,atoi)
 #define FPVAL(name) ANYVAL(name,atof)
-#define TIMEVAL(name) ANYVAL(name,string2timecode)
+#define TIMEVAL(name) \
+       } else if (strcasecmp(tname, #name) == 0) { \
+               target->name = string2timecode(track->library, token); \
+               ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
+
 #define STYLEVAL(name) \
        } else if (strcasecmp(tname, #name) == 0) { \
                target->name = lookup_style(track, token); \
-               ass_msg(MSGL_DBG2, "%s = %s", #name, token);
+               ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
 
 #define ALIAS(alias,name) \
        if (strcasecmp(tname, #alias) == 0) {tname = #name;}
@@ -318,7 +326,7 @@ static int process_event_tail(ass_track_t *track, ass_event_t *event,
                 if (last >= event->Text && *last == '\r')
                     *last = 0;
             }
-            ass_msg(MSGL_DBG2, "Text = %s", event->Text);
+            ass_msg(track->library, MSGL_DBG2, "Text = %s", event->Text);
             event->Duration -= event->Start;
             free(format);
             return 0;           // "Text" is always the last
@@ -458,7 +466,7 @@ static int process_style(ass_track_t *track, char *str)
 
     q = format = strdup(track->style_format);
 
-    ass_msg(MSGL_V, "[%p] Style: %s", track, str);
+    ass_msg(track->library, MSGL_V, "[%p] Style: %s", track, str);
 
     sid = ass_alloc_style(track);
 
@@ -535,7 +543,7 @@ static int process_styles_line(ass_track_t *track, char *str)
         char *p = str + 7;
         skip_spaces(&p);
         track->style_format = strdup(p);
-        ass_msg(MSGL_DBG2, "Style format: %s",
+        ass_msg(track->library, MSGL_DBG2, "Style format: %s",
                track->style_format);
     } else if (!strncmp(str, "Style:", 6)) {
         char *p = str + 6;
@@ -565,14 +573,13 @@ static void event_format_fallback(ass_track_t *track)
 {
     track->parser_priv->state = PST_EVENTS;
     if (track->track_type == TRACK_TYPE_SSA)
-        track->event_format =
-            strdup
-            ("Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text");
+        track->event_format = strdup("Format: Marked, Start, End, Style, "
+            "Name, MarginL, MarginR, MarginV, Effect, Text");
     else
-        track->event_format =
-            strdup
-            ("Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text");
-    ass_msg(MSGL_V, "No event format found, using fallback");
+        track->event_format = strdup("Format: Layer, Start, End, Style, "
+            "Actor, MarginL, MarginR, MarginV, Effect, Text");
+    ass_msg(track->library, MSGL_V,
+            "No event format found, using fallback");
 }
 
 static int process_events_line(ass_track_t *track, char *str)
@@ -581,7 +588,7 @@ static int process_events_line(ass_track_t *track, char *str)
         char *p = str + 7;
         skip_spaces(&p);
         track->event_format = strdup(p);
-        ass_msg(MSGL_DBG2, "Event format: %s", track->event_format);
+        ass_msg(track->library, MSGL_DBG2, "Event format: %s", track->event_format);
     } else if (!strncmp(str, "Dialogue:", 9)) {
         // This should never be reached for embedded subtitles.
         // They have slightly different format and are parsed in ass_process_chunk,
@@ -601,7 +608,7 @@ static int process_events_line(ass_track_t *track, char *str)
 
         process_event_tail(track, event, str, 0);
     } else {
-        ass_msg(MSGL_V, "Not understood: '%s'", str);
+        ass_msg(track->library, MSGL_V, "Not understood: '%s'", str);
     }
     return 0;
 }
@@ -636,11 +643,11 @@ static int decode_font(ass_track_t *track)
     int dsize;                  // decoded size
     unsigned char *buf = 0;
 
-    ass_msg(MSGL_V, "Font: %d bytes encoded data",
-           track->parser_priv->fontdata_used);
+    ass_msg(track->library, MSGL_V, "Font: %d bytes encoded data",
+            track->parser_priv->fontdata_used);
     size = track->parser_priv->fontdata_used;
     if (size % 4 == 1) {
-        ass_msg(MSGL_ERR, "Bad encoded data size");
+        ass_msg(track->library, MSGL_ERR, "Bad encoded data size");
         goto error_decode_font;
     }
     buf = malloc(size / 4 * 3 + 2);
@@ -686,19 +693,20 @@ static int process_fonts_line(ass_track_t *track, char *str)
             decode_font(track);
         }
         track->parser_priv->fontname = strdup(p);
-        ass_msg(MSGL_V, "Fontname: %s",
+        ass_msg(track->library, MSGL_V, "Fontname: %s",
                track->parser_priv->fontname);
         return 0;
     }
 
     if (!track->parser_priv->fontname) {
-        ass_msg(MSGL_V, "Not understood: '%s'", str);
+        ass_msg(track->library, MSGL_V, "Not understood: '%s'", str);
         return 0;
     }
 
     len = strlen(str);
     if (len > 80) {
-        ass_msg(MSGL_WARN, "Font line too long: %d, %s", len, str);
+        ass_msg(track->library, MSGL_WARN, "Font line too long: %d, %s",
+                len, str);
         return 0;
     }
     if (track->parser_priv->fontdata_used + len >
@@ -801,7 +809,7 @@ void ass_process_data(ass_track_t *track, char *data, int size)
     memcpy(str, data, size);
     str[size] = '\0';
 
-    ass_msg(MSGL_V, "Event: %s", str);
+    ass_msg(track->library, MSGL_V, "Event: %s", str);
     process_text(track, str);
     free(str);
 }
@@ -852,14 +860,14 @@ void ass_process_chunk(ass_track_t *track, char *data, int size,
     ass_event_t *event;
 
     if (!track->event_format) {
-        ass_msg(MSGL_WARN, "Event format header missing");
+        ass_msg(track->library, MSGL_WARN, "Event format header missing");
         return;
     }
 
     str = malloc(size + 1);
     memcpy(str, data, size);
     str[size] = '\0';
-    ass_msg(MSGL_V, "Event at %" PRId64 ", +%" PRId64 ": %s",
+    ass_msg(track->library, MSGL_V, "Event at %" PRId64 ", +%" PRId64 ": %s",
            (int64_t) timecode, (int64_t) duration, str);
 
     eid = ass_alloc_event(track);
@@ -898,7 +906,8 @@ void ass_process_chunk(ass_track_t *track, char *data, int size,
  * \param size buffer size
  * \return a pointer to recoded buffer, caller is responsible for freeing it
 **/
-static char *sub_recode(char *data, size_t size, char *codepage)
+static char *sub_recode(ass_library_t *library, char *data, size_t size,
+                        char *codepage)
 {
     iconv_t icdsc;
     char *tocp = "UTF-8";
@@ -913,14 +922,14 @@ static char *sub_recode(char *data, size_t size, char *codepage)
             || sscanf(codepage, "ENCA:%2s:%99s", enca_lang,
                       enca_fallback) == 2) {
             cp_tmp =
-                ass_guess_buffer_cp((unsigned char *) data, size, enca_lang,
-                                enca_fallback);
+                ass_guess_buffer_cp(library, (unsigned char *) data, size,
+                                    enca_lang, enca_fallback);
         }
 #endif
         if ((icdsc = iconv_open(tocp, cp_tmp)) != (iconv_t) (-1)) {
-            ass_msg(MSGL_V, "Opened iconv descriptor");
+            ass_msg(library, MSGL_V, "Opened iconv descriptor");
         } else
-            ass_msg(MSGL_ERR, "Error opening iconv descriptor");
+            ass_msg(library, MSGL_ERR, "Error opening iconv descriptor");
     }
 
     {
@@ -951,7 +960,7 @@ static char *sub_recode(char *data, size_t size, char *codepage)
                     osize += size;
                     oleft += size;
                 } else {
-                    ass_msg(MSGL_WARN, "Error recoding file");
+                    ass_msg(library, MSGL_WARN, "Error recoding file");
                     return NULL;
                 }
             } else if (clear)
@@ -963,7 +972,7 @@ static char *sub_recode(char *data, size_t size, char *codepage)
     if (icdsc != (iconv_t) (-1)) {
         (void) iconv_close(icdsc);
         icdsc = (iconv_t) (-1);
-        ass_msg(MSGL_V, "Closed iconv descriptor");
+        ass_msg(library, MSGL_V, "Closed iconv descriptor");
     }
 
     return outbuf;
@@ -976,7 +985,7 @@ static char *sub_recode(char *data, size_t size, char *codepage)
  * \param bufsize out: file size
  * \return pointer to file contents. Caller is responsible for its deallocation.
  */
-static char *read_file(char *fname, size_t *bufsize)
+static char *read_file(ass_library_t *library, char *fname, size_t *bufsize)
 {
     int res;
     long sz;
@@ -985,12 +994,14 @@ static char *read_file(char *fname, size_t *bufsize)
 
     FILE *fp = fopen(fname, "rb");
     if (!fp) {
-        ass_msg(MSGL_WARN, "ass_read_file(%s): fopen failed", fname);
+        ass_msg(library, MSGL_WARN,
+                "ass_read_file(%s): fopen failed", fname);
         return 0;
     }
     res = fseek(fp, 0, SEEK_END);
     if (res == -1) {
-        ass_msg(MSGL_WARN, "ass_read_file(%s): fseek failed", fname);
+        ass_msg(library, MSGL_WARN,
+                "ass_read_file(%s): fseek failed", fname);
         fclose(fp);
         return 0;
     }
@@ -999,14 +1010,14 @@ static char *read_file(char *fname, size_t *bufsize)
     rewind(fp);
 
     if (sz > 10 * 1024 * 1024) {
-        ass_msg(MSGL_INFO,
+        ass_msg(library, MSGL_INFO,
                "ass_read_file(%s): Refusing to load subtitles "
                "larger than 10MiB", fname);
         fclose(fp);
         return 0;
     }
 
-    ass_msg(MSGL_V, "File size: %ld", sz);
+    ass_msg(library, MSGL_V, "File size: %ld", sz);
 
     buf = malloc(sz + 1);
     assert(buf);
@@ -1014,7 +1025,7 @@ static char *read_file(char *fname, size_t *bufsize)
     do {
         res = fread(buf + bytes_read, 1, sz - bytes_read, fp);
         if (res <= 0) {
-            ass_msg(MSGL_INFO, "Read failed, %d: %s", errno,
+            ass_msg(library, MSGL_INFO, "Read failed, %d: %s", errno,
                     strerror(errno));
             fclose(fp);
             free(buf);
@@ -1080,7 +1091,7 @@ ass_track_t *ass_read_memory(ass_library_t *library, char *buf,
 
 #ifdef CONFIG_ICONV
     if (codepage)
-        buf = sub_recode(buf, bufsize, codepage);
+        buf = sub_recode(library, buf, bufsize, codepage);
     if (!buf)
         return 0;
     else
@@ -1092,23 +1103,24 @@ ass_track_t *ass_read_memory(ass_library_t *library, char *buf,
     if (!track)
         return 0;
 
-    ass_msg(MSGL_INFO, "Added subtitle file: "
+    ass_msg(library, MSGL_INFO, "Added subtitle file: "
             "<memory> (%d styles, %d events)",
             track->n_styles, track->n_events);
     return track;
 }
 
-static char *read_file_recode(char *fname, char *codepage, size_t *size)
+static char *read_file_recode(ass_library_t *library, char *fname,
+                              char *codepage, size_t *size)
 {
     char *buf;
     size_t bufsize;
 
-    buf = read_file(fname, &bufsize);
+    buf = read_file(library, fname, &bufsize);
     if (!buf)
         return 0;
 #ifdef CONFIG_ICONV
     if (codepage) {
-        char *tmpbuf = sub_recode(buf, bufsize, codepage);
+        char *tmpbuf = sub_recode(library, buf, bufsize, codepage);
         free(buf);
         buf = tmpbuf;
     }
@@ -1133,7 +1145,7 @@ ass_track_t *ass_read_file(ass_library_t *library, char *fname,
     ass_track_t *track;
     size_t bufsize;
 
-    buf = read_file_recode(fname, codepage, &bufsize);
+    buf = read_file_recode(library, fname, codepage, &bufsize);
     if (!buf)
         return 0;
     track = parse_memory(library, buf);
@@ -1143,7 +1155,8 @@ ass_track_t *ass_read_file(ass_library_t *library, char *fname,
 
     track->name = strdup(fname);
 
-    ass_msg(MSGL_INFO, "Added subtitle file: '%s' (%d styles, %d events)",
+    ass_msg(library, MSGL_INFO,
+            "Added subtitle file: '%s' (%d styles, %d events)",
             fname, track->n_styles, track->n_events);
 
     return track;
@@ -1158,13 +1171,13 @@ int ass_read_styles(ass_track_t *track, char *fname, char *codepage)
     parser_state_t old_state;
     size_t sz;
 
-    buf = read_file(fname, &sz);
+    buf = read_file(track->library, fname, &sz);
     if (!buf)
         return 1;
 #ifdef CONFIG_ICONV
     if (codepage) {
         char *tmpbuf;
-        tmpbuf = sub_recode(buf, sz, codepage);
+        tmpbuf = sub_recode(track->library, buf, sz, codepage);
         free(buf);
         buf = tmpbuf;
     }
index d911e9911c3e7307bfcde9490ba519a25730959b..e0160d62cc6542bfdb70bf0562db1818fb080200 100644 (file)
@@ -22,6 +22,7 @@
 #define LIBASS_ASS_H
 
 #include <stdio.h>
+#include <stdarg.h>
 #include "ass_types.h"
 
 /// Libass renderer object. Contents are private.
@@ -69,6 +70,9 @@ void ass_set_style_overrides(ass_library_t *priv, char **list);
 
 void ass_process_force_style(ass_track_t *track);
 
+void ass_set_message_cb(ass_library_t *priv,
+                        void (*msg_cb)(int, char *, va_list *));
+
 /**
  * \brief initialize the renderer
  * \param priv library handle
index a72caadb05ded6e75e3da49a2d449a2f5929aae4..c8cd8be7a4b12f2742353ce5b3b3a529e4270e10 100644 (file)
@@ -165,7 +165,7 @@ static bitmap_t *copy_bitmap(const bitmap_t *src)
     return dst;
 }
 
-static int check_glyph_area(FT_Glyph glyph)
+static int check_glyph_area(ass_library_t *library, FT_Glyph glyph)
 {
     FT_BBox bbox;
     long long dx, dy;
@@ -173,14 +173,15 @@ static int check_glyph_area(FT_Glyph glyph)
     dx = bbox.xMax - bbox.xMin;
     dy = bbox.yMax - bbox.yMin;
     if (dx * dy > 8000000) {
-        ass_msg(MSGL_WARN, "Glyph bounding box too large: %dx%dpx",
+        ass_msg(library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx",
                (int) dx, (int) dy);
         return 1;
     } else
         return 0;
 }
 
-static bitmap_t *glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
+static bitmap_t *glyph_to_bitmap_internal(ass_library_t *library,
+                                          FT_Glyph glyph, int bord)
 {
     FT_BitmapGlyph bg;
     FT_Bitmap *bit;
@@ -191,11 +192,11 @@ static bitmap_t *glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
     int i;
     int error;
 
-    if (check_glyph_area(glyph))
+    if (check_glyph_area(library, glyph))
         return 0;
     error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0);
     if (error) {
-        ass_msg(MSGL_WARN, "FT_Glyph_To_Bitmap error %d",
+        ass_msg(library, MSGL_WARN, "FT_Glyph_To_Bitmap error %d",
                error);
         return 0;
     }
@@ -203,7 +204,7 @@ static bitmap_t *glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
     bg = (FT_BitmapGlyph) glyph;
     bit = &(bg->bitmap);
     if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) {
-        ass_msg(MSGL_WARN, "Unsupported pixel mode: %d",
+        ass_msg(library, MSGL_WARN, "Unsupported pixel mode: %d",
                (int) (bit->pixel_mode));
         FT_Done_Glyph(glyph);
         return 0;
@@ -471,7 +472,7 @@ static void be_blur(unsigned char *buf, int w, int h)
     }
 }
 
-int glyph_to_bitmap(ass_synth_priv_t *priv_blur,
+int glyph_to_bitmap(ass_library_t *library, ass_synth_priv_t *priv_blur,
                     FT_Glyph glyph, FT_Glyph outline_glyph,
                     bitmap_t **bm_g, bitmap_t **bm_o, bitmap_t **bm_s,
                     int be, double blur_radius, FT_Vector shadow_offset)
@@ -487,12 +488,12 @@ int glyph_to_bitmap(ass_synth_priv_t *priv_blur,
     *bm_g = *bm_o = *bm_s = 0;
 
     if (glyph)
-        *bm_g = glyph_to_bitmap_internal(glyph, bord);
+        *bm_g = glyph_to_bitmap_internal(library, glyph, bord);
     if (!*bm_g)
         return 1;
 
     if (outline_glyph) {
-        *bm_o = glyph_to_bitmap_internal(outline_glyph, bord);
+        *bm_o = glyph_to_bitmap_internal(library, outline_glyph, bord);
         if (!*bm_o) {
             ass_free_bitmap(*bm_g);
             return 1;
index f6b138058e991aee7c6edf632c9602c75cf28eb9..2e34a5c6df6e515c3b41f95e9a2001a30cb74914 100644 (file)
@@ -24,6 +24,8 @@
 #include <ft2build.h>
 #include FT_GLYPH_H
 
+#include "ass.h"
+
 typedef struct ass_synth_priv_s ass_synth_priv_t;
 
 ass_synth_priv_t *ass_synth_init(double);
@@ -44,10 +46,10 @@ typedef struct bitmap_s {
  * \param bm_g out: pointer to the bitmap of glyph shadow is returned here
  * \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
  */
-int glyph_to_bitmap(ass_synth_priv_t *priv_blur, FT_Glyph glyph,
-                    FT_Glyph outline_glyph, bitmap_t **bm_g,
-                    bitmap_t **bm_o, bitmap_t **bm_s, int be,
-                    double blur_radius, FT_Vector shadow_offset);
+int glyph_to_bitmap(ass_library_t *library, ass_synth_priv_t *priv_blur,
+                    FT_Glyph glyph, FT_Glyph outline_glyph,
+                    bitmap_t **bm_g, bitmap_t **bm_o, bitmap_t **bm_s,
+                    int be, double blur_radius, FT_Vector shadow_offset);
 
 void ass_free_bitmap(bitmap_t *bm);
 
index adee0cc4591bdc01a2e831072bc7a89df2d30a93..ed44a2f1bf7fe8ed28663924a52b01622d0ce624 100644 (file)
@@ -51,12 +51,14 @@ static void hashmap_item_dtor(void *key, size_t key_size, void *value,
     free(value);
 }
 
-hashmap_t *hashmap_init(size_t key_size, size_t value_size, int nbuckets,
+hashmap_t *hashmap_init(ass_library_t *library, size_t key_size,
+                        size_t value_size, int nbuckets,
                         hashmap_item_dtor_t item_dtor,
                         hashmap_key_compare_t key_compare,
                         hashmap_hash_t hash)
 {
     hashmap_t *map = calloc(1, sizeof(hashmap_t));
+    map->library = library;
     map->nbuckets = nbuckets;
     map->key_size = key_size;
     map->value_size = value_size;
@@ -72,7 +74,7 @@ void hashmap_done(hashmap_t *map)
     int i;
     // print stats
     if (map->count > 0 || map->hit_count + map->miss_count > 0)
-        ass_msg(MSGL_V,
+        ass_msg(map->library, MSGL_V,
                "cache statistics: \n  total accesses: %d\n  hits: %d\n  "
                "misses: %d\n  object count: %d",
                map->hit_count + map->miss_count, map->hit_count,
@@ -179,10 +181,10 @@ void *ass_font_cache_add(hashmap_t *font_cache, ass_font_t *font)
     return hashmap_insert(font_cache, &(font->desc), font);
 }
 
-hashmap_t *ass_font_cache_init(void)
+hashmap_t *ass_font_cache_init(ass_library_t *library)
 {
     hashmap_t *font_cache;
-    font_cache = hashmap_init(sizeof(ass_font_desc_t),
+    font_cache = hashmap_init(library, sizeof(ass_font_desc_t),
                               sizeof(ass_font_t),
                               1000,
                               font_hash_dtor, font_compare, font_desc_hash);
@@ -235,10 +237,11 @@ bitmap_hash_val_t *cache_find_bitmap(hashmap_t *bitmap_cache,
     return hashmap_find(bitmap_cache, key);
 }
 
-hashmap_t *ass_bitmap_cache_init(void)
+hashmap_t *ass_bitmap_cache_init(ass_library_t *library)
 {
     hashmap_t *bitmap_cache;
-    bitmap_cache = hashmap_init(sizeof(bitmap_hash_key_t),
+    bitmap_cache = hashmap_init(library,
+                                sizeof(bitmap_hash_key_t),
                                 sizeof(bitmap_hash_val_t),
                                 0xFFFF + 13,
                                 bitmap_hash_dtor, bitmap_compare,
@@ -253,8 +256,10 @@ void ass_bitmap_cache_done(hashmap_t *bitmap_cache)
 
 hashmap_t *ass_bitmap_cache_reset(hashmap_t *bitmap_cache)
 {
+    ass_library_t *lib = bitmap_cache->library;
+
     ass_bitmap_cache_done(bitmap_cache);
-    return ass_bitmap_cache_init();
+    return ass_bitmap_cache_init(lib);
 }
 
 //---------------------------------
@@ -289,10 +294,10 @@ glyph_hash_val_t *cache_find_glyph(hashmap_t *glyph_cache,
     return hashmap_find(glyph_cache, key);
 }
 
-hashmap_t *ass_glyph_cache_init(void)
+hashmap_t *ass_glyph_cache_init(ass_library_t *library)
 {
     hashmap_t *glyph_cache;
-    glyph_cache = hashmap_init(sizeof(glyph_hash_key_t),
+    glyph_cache = hashmap_init(library, sizeof(glyph_hash_key_t),
                                sizeof(glyph_hash_val_t),
                                0xFFFF + 13,
                                glyph_hash_dtor, glyph_compare, glyph_hash);
@@ -306,8 +311,10 @@ void ass_glyph_cache_done(hashmap_t *glyph_cache)
 
 hashmap_t *ass_glyph_cache_reset(hashmap_t *glyph_cache)
 {
+    ass_library_t *lib = glyph_cache->library;
+
     ass_glyph_cache_done(glyph_cache);
-    return ass_glyph_cache_init();
+    return ass_glyph_cache_init(lib);
 }
 
 
@@ -342,10 +349,10 @@ composite_hash_val_t *cache_find_composite(hashmap_t *composite_cache,
     return hashmap_find(composite_cache, key);
 }
 
-hashmap_t *ass_composite_cache_init(void)
+hashmap_t *ass_composite_cache_init(ass_library_t *library)
 {
     hashmap_t *composite_cache;
-    composite_cache = hashmap_init(sizeof(composite_hash_key_t),
+    composite_cache = hashmap_init(library, sizeof(composite_hash_key_t),
                                    sizeof(composite_hash_val_t),
                                    0xFFFF + 13,
                                    composite_hash_dtor, composite_compare,
@@ -360,6 +367,8 @@ void ass_composite_cache_done(hashmap_t *composite_cache)
 
 hashmap_t *ass_composite_cache_reset(hashmap_t *composite_cache)
 {
+    ass_library_t *lib = composite_cache->library;
+
     ass_composite_cache_done(composite_cache);
-    return ass_composite_cache_init();
+    return ass_composite_cache_init(lib);
 }
index d8de97a1860d6834611e19d49d5a263e4e9936a9..004a4b67c0594eb83222991c7dc3c686a46e4a04 100644 (file)
@@ -49,9 +49,11 @@ typedef struct hashmap_s {
     int hit_count;
     int miss_count;
     int count;
+    ass_library_t *library;
 } hashmap_t;
 
-hashmap_t *hashmap_init(size_t key_size, size_t value_size, int nbuckets,
+hashmap_t *hashmap_init(ass_library_t *library, size_t key_size,
+                        size_t value_size, int nbuckets,
                         hashmap_item_dtor_t item_dtor,
                         hashmap_key_compare_t key_compare,
                         hashmap_hash_t hash);
@@ -59,7 +61,7 @@ void hashmap_done(hashmap_t *map);
 void *hashmap_insert(hashmap_t *map, void *key, void *value);
 void *hashmap_find(hashmap_t *map, void *key);
 
-hashmap_t *ass_font_cache_init(void);
+hashmap_t *ass_font_cache_init(ass_library_t *library);
 ass_font_t *ass_font_cache_find(hashmap_t *, ass_font_desc_t *desc);
 void *ass_font_cache_add(hashmap_t *, ass_font_t *font);
 void ass_font_cache_done(hashmap_t *);
@@ -74,7 +76,7 @@ typedef struct bitmap_hash_val_s {
     bitmap_t *bm_s;
 } bitmap_hash_val_t;
 
-hashmap_t *ass_bitmap_cache_init(void);
+hashmap_t *ass_bitmap_cache_init(ass_library_t *library);
 void *cache_add_bitmap(hashmap_t *, bitmap_hash_key_t *key,
                        bitmap_hash_val_t *val);
 bitmap_hash_val_t *cache_find_bitmap(hashmap_t *bitmap_cache,
@@ -88,7 +90,7 @@ typedef struct composite_hash_val_s {
     unsigned char *b;
 } composite_hash_val_t;
 
-hashmap_t *ass_composite_cache_init(void);
+hashmap_t *ass_composite_cache_init(ass_library_t *library);
 void *cache_add_composite(hashmap_t *, composite_hash_key_t *key,
                           composite_hash_val_t *val);
 composite_hash_val_t *cache_find_composite(hashmap_t *composite_cache,
@@ -105,7 +107,7 @@ typedef struct glyph_hash_val_s {
     int asc, desc;              // ascender/descender of a drawing
 } glyph_hash_val_t;
 
-hashmap_t *ass_glyph_cache_init(void);
+hashmap_t *ass_glyph_cache_init(ass_library_t *library);
 void *cache_add_glyph(hashmap_t *, glyph_hash_key_t *key,
                       glyph_hash_val_t *val);
 glyph_hash_val_t *cache_find_glyph(hashmap_t *glyph_cache,
index c05a962929ea99702ef1414856c7e34db6340ffe..f75bbd9ad94187e194fd88f2ac795694e363b6e0 100644 (file)
@@ -139,8 +139,9 @@ static void drawing_finish(ass_drawing_t *drawing)
     for (i = 0; i < ol->n_points; i++)
         ol->points[i].y += offset;
 
-    ass_msg(MSGL_V, "Parsed drawing with %d points and %d contours",
-            ol->n_points, ol->n_contours);
+    ass_msg(drawing->library, MSGL_V,
+            "Parsed drawing with %d points and %d contours", ol->n_points,
+            ol->n_contours);
 }
 
 /*
@@ -364,6 +365,7 @@ ass_drawing_t *ass_drawing_new(void *fontconfig_priv, ass_font_t *font,
     drawing->size = DRAWING_INITIAL_SIZE;
 
     drawing->ftlibrary = lib;
+    drawing->library = font->library;
     drawing_make_glyph(drawing, fontconfig_priv, font, hint);
 
     drawing->scale_x = 1.;
index 323c05deedc001bb3d64e1df9ea2aecc23792bd9..dfd68f01bf2e944017e40d972ee768a68092c2f2 100644 (file)
@@ -58,6 +58,7 @@ typedef struct ass_drawing_s {
 
     // private
     FT_Library ftlibrary;   // FT library instance, needed for font ops
+    ass_library_t *library;
     int size;           // current buffer size
     ass_drawing_token_t *tokens;    // tokenized drawing
     int max_points;     // current maximum size
index 76c4793e19dcce722595d68af9b19fa1299570c2..34ae292c466ceac7a4bfb36b9cc563d61765764d 100644 (file)
@@ -39,7 +39,7 @@
  * Select Microfost Unicode CharMap, if the font has one.
  * Otherwise, let FreeType decide.
  */
-static void charmap_magic(FT_Face face)
+static void charmap_magic(ass_library_t *library, FT_Face face)
 {
     int i;
     for (i = 0; i < face->num_charmaps; ++i) {
@@ -56,10 +56,11 @@ static void charmap_magic(FT_Face face)
 
     if (!face->charmap) {
         if (face->num_charmaps == 0) {
-            ass_msg(MSGL_WARN, "Font face with no charmaps");
+            ass_msg(library, MSGL_WARN, "Font face with no charmaps");
             return;
         }
-        ass_msg(MSGL_WARN, "No charmap autodetected, trying the first one");
+        ass_msg(library, MSGL_WARN,
+                "No charmap autodetected, trying the first one");
         FT_Set_Charmap(face, face->charmaps[0]);
         return;
     }
@@ -125,7 +126,7 @@ static int add_face(void *fc_priv, ass_font_t *font, uint32_t ch)
         return -1;
 
     path =
-        fontconfig_select(fc_priv, font->desc.family,
+        fontconfig_select(font->library, fc_priv, font->desc.family,
                           font->desc.treat_family_as_pattern,
                           font->desc.bold, font->desc.italic, &index, ch);
     if (!path)
@@ -140,19 +141,21 @@ static int add_face(void *fc_priv, ass_font_t *font, uint32_t ch)
                                font->library->fontdata[mem_idx].size, 0,
                                &face);
         if (error) {
-            ass_msg(MSGL_WARN, "Error opening memory font: '%s'", path);
+            ass_msg(font->library, MSGL_WARN,
+                    "Error opening memory font: '%s'", path);
             free(path);
             return -1;
         }
     } else {
         error = FT_New_Face(font->ftlibrary, path, index, &face);
         if (error) {
-            ass_msg(MSGL_WARN, "Error opening font: '%s', %d", path, index);
+            ass_msg(font->library, MSGL_WARN,
+                    "Error opening font: '%s', %d", path, index);
             free(path);
             return -1;
         }
     }
-    charmap_magic(face);
+    charmap_magic(font->library, face);
     buggy_font_workaround(face);
 
     font->faces[font->n_faces++] = face;
@@ -384,7 +387,7 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ass_font_t *font,
 #ifdef CONFIG_FONTCONFIG
     if (index == 0) {
         int face_idx;
-        ass_msg(MSGL_INFO,
+        ass_msg(font->library, MSGL_INFO,
                 "Glyph 0x%X not found, selecting one more "
                 "font for (%s, %d, %d)", ch, font->desc.family,
                 font->desc.bold, font->desc.italic);
@@ -393,9 +396,10 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ass_font_t *font,
             face = font->faces[face_idx];
             index = FT_Get_Char_Index(face, ch);
             if (index == 0) {
-                ass_msg(MSGL_ERR, "Glyph 0x%X not found in font "
-                        "for (%s, %d, %d)", ch, font->desc.family,
-                        font->desc.bold, font->desc.italic);
+                ass_msg(font->library, MSGL_ERR,
+                        "Glyph 0x%X not found in font for (%s, %d, %d)",
+                        ch, font->desc.family, font->desc.bold,
+                        font->desc.italic);
             }
         }
     }
@@ -418,7 +422,8 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ass_font_t *font,
 
     error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP | flags);
     if (error) {
-        ass_msg(MSGL_WARN, "Error loading glyph, index %d", index);
+        ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d",
+                index);
         return 0;
     }
 #if (FREETYPE_MAJOR > 2) || \
@@ -432,7 +437,8 @@ FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ass_font_t *font,
 #endif
     error = FT_Get_Glyph(face->glyph, &glyph);
     if (error) {
-        ass_msg(MSGL_WARN, "Error loading glyph, index %d", index);
+        ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d",
+                index);
         return 0;
     }
 
index e23c4f2082d92600b8586e92c9f55cd532b5be04..d8d64e2299b33461e4fd1303a8764ade22a96c13 100644 (file)
@@ -71,9 +71,10 @@ struct fc_instance_s {
  * \param code: the character that should be present in the font, can be 0
  * \return font file path
 */
-static char *_select_font(fc_instance_t *priv, const char *family,
-                          int treat_family_as_pattern, unsigned bold,
-                          unsigned italic, int *index, uint32_t code)
+static char *_select_font(ass_library_t *library, fc_instance_t *priv,
+                          const char *family, int treat_family_as_pattern,
+                          unsigned bold, unsigned italic, int *index,
+                          uint32_t code)
 {
     FcBool rc;
     FcResult result;
@@ -193,7 +194,7 @@ static char *_select_font(fc_instance_t *priv, const char *family,
     if (!treat_family_as_pattern &&
         !(r_family && strcasecmp((const char *) r_family, family) == 0) &&
         !(r_fullname && strcasecmp((const char *) r_fullname, family) == 0))
-        ass_msg(MSGL_WARN,
+        ass_msg(library, MSGL_WARN,
                "fontconfig: Selected font is not the requested one: "
                "'%s' != '%s'",
                (const char *) (r_fullname ? r_fullname : r_family), family);
@@ -214,7 +215,7 @@ static char *_select_font(fc_instance_t *priv, const char *family,
     if (result != FcResultMatch)
         r_embolden = 0;
 
-    ass_msg(MSGL_V,
+    ass_msg(library, MSGL_V,
            "Font info: family '%s', style '%s', fullname '%s',"
            " slant %d, weight %d%s", (const char *) r_family,
            (const char *) r_style, (const char *) r_fullname, r_slant,
@@ -241,9 +242,10 @@ static char *_select_font(fc_instance_t *priv, const char *family,
  * \param code: the character that should be present in the font, can be 0
  * \return font file path
 */
-char *fontconfig_select(fc_instance_t *priv, const char *family,
-                        int treat_family_as_pattern, unsigned bold,
-                        unsigned italic, int *index, uint32_t code)
+char *fontconfig_select(ass_library_t *library, fc_instance_t *priv,
+                        const char *family, int treat_family_as_pattern,
+                        unsigned bold, unsigned italic, int *index,
+                        uint32_t code)
 {
     char *res = 0;
     if (!priv->config) {
@@ -252,33 +254,34 @@ char *fontconfig_select(fc_instance_t *priv, const char *family,
     }
     if (family && *family)
         res =
-            _select_font(priv, family, treat_family_as_pattern, bold,
-                         italic, index, code);
+            _select_font(library, priv, family, treat_family_as_pattern,
+                         bold, italic, index, code);
     if (!res && priv->family_default) {
         res =
-            _select_font(priv, priv->family_default, 0, bold, italic, index,
-                         code);
+            _select_font(library, priv, priv->family_default, 0, bold,
+                         italic, index, code);
         if (res)
-            ass_msg(MSGL_WARN, "fontconfig_select: Using default font "
-                    "family: (%s, %d, %d) -> %s, %d",
+            ass_msg(library, MSGL_WARN, "fontconfig_select: Using default "
+                    "font family: (%s, %d, %d) -> %s, %d",
                     family, bold, italic, res, *index);
     }
     if (!res && priv->path_default) {
         res = priv->path_default;
         *index = priv->index_default;
-        ass_msg(MSGL_WARN, "fontconfig_select: Using default font: "
+        ass_msg(library, MSGL_WARN, "fontconfig_select: Using default font: "
                 "(%s, %d, %d) -> %s, %d", family, bold, italic,
                 res, *index);
     }
     if (!res) {
-        res = _select_font(priv, "Arial", 0, bold, italic, index, code);
+        res = _select_font(library, priv, "Arial", 0, bold, italic,
+                           index, code);
         if (res)
-            ass_msg(MSGL_WARN, "fontconfig_select: Using 'Arial' font "
-                    "family: (%s, %d, %d) -> %s, %d", family, bold, italic,
-                    res, *index);
+            ass_msg(library, MSGL_WARN, "fontconfig_select: Using 'Arial' "
+                    "font family: (%s, %d, %d) -> %s, %d", family, bold,
+                    italic, res, *index);
     }
     if (res)
-        ass_msg(MSGL_V,
+        ass_msg(library, MSGL_V,
                 "fontconfig_select: (%s, %d, %d) -> %s, %d", family, bold,
                 italic, res, *index);
     return res;
@@ -354,11 +357,11 @@ static void process_fontdata(fc_instance_t *priv, ass_library_t *library,
         res = mkdir(fonts_dir);
 #endif
         if (res) {
-            ass_msg(MSGL_WARN, "Failed to create directory '%s'",
+            ass_msg(library, MSGL_WARN, "Failed to create directory '%s'",
                     fonts_dir);
         }
     } else if (!S_ISDIR(st.st_mode)) {
-        ass_msg(MSGL_WARN, "Not a directory: '%s'", fonts_dir);
+        ass_msg(library, MSGL_WARN, "Not a directory: '%s'", fonts_dir);
     }
 
     fname = validate_fname((char *) name);
@@ -384,7 +387,7 @@ static void process_fontdata(fc_instance_t *priv, ass_library_t *library,
         rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data,
                                 data_size, face_index, &face);
         if (rc) {
-            ass_msg(MSGL_WARN, "Error opening memory font: %s",
+            ass_msg(library, MSGL_WARN, "Error opening memory font: %s",
                    name);
             return;
         }
@@ -394,21 +397,21 @@ static void process_fontdata(fc_instance_t *priv, ass_library_t *library,
             FcFreeTypeQueryFace(face, (unsigned char *) name, 0,
                                 FcConfigGetBlanks(priv->config));
         if (!pattern) {
-            ass_msg(MSGL_WARN, "%s failed", "FcFreeTypeQueryFace");
+            ass_msg(library, MSGL_WARN, "%s failed", "FcFreeTypeQueryFace");
             FT_Done_Face(face);
             return;
         }
 
         fset = FcConfigGetFonts(priv->config, FcSetSystem);     // somehow it failes when asked for FcSetApplication
         if (!fset) {
-            ass_msg(MSGL_WARN, "%s failed", "FcConfigGetFonts");
+            ass_msg(library, MSGL_WARN, "%s failed", "FcConfigGetFonts");
             FT_Done_Face(face);
             return;
         }
 
         res = FcFontSetAdd(fset, pattern);
         if (!res) {
-            ass_msg(MSGL_WARN, "%s failed", "FcFontSetAdd");
+            ass_msg(library, MSGL_WARN, "%s failed", "FcFontSetAdd");
             FT_Done_Face(face);
             return;
         }
@@ -436,7 +439,7 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
     int i;
 
     if (!fc) {
-        ass_msg(MSGL_WARN,
+        ass_msg(library, MSGL_WARN,
                "Fontconfig disabled, only default font will be used.");
         goto exit;
     }
@@ -454,7 +457,7 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
     }
 
     if (!rc || !priv->config) {
-        ass_msg(MSGL_FATAL, "%s failed", "FcInitLoadConfigAndFonts");
+        ass_msg(library, MSGL_FATAL, "%s failed", "FcInitLoadConfigAndFonts");
         goto exit;
     }
 
@@ -463,10 +466,10 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
 
     if (dir) {
         if (FcDirCacheValid((const FcChar8 *) dir) == FcFalse) {
-            ass_msg(MSGL_INFO, "Updating font cache");
+            ass_msg(library, MSGL_INFO, "Updating font cache");
             if (FcGetVersion() >= 20390 && FcGetVersion() < 20400)
-                ass_msg(MSGL_WARN, "Beta versions of fontconfig are not "
-                        "supported. Update before reporting any bugs");
+                ass_msg(library, MSGL_WARN, "Beta versions of fontconfig"
+                        "are not supported. Update before reporting any bugs");
             // FontConfig >= 2.4.0 updates cache automatically in FcConfigAppFontAddDir()
             if (FcGetVersion() < 20390) {
                 FcFontSet *fcs;
@@ -475,7 +478,7 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
                 fss = FcStrSetCreate();
                 rc = FcStrSetAdd(fss, (const FcChar8 *) dir);
                 if (!rc) {
-                    ass_msg(MSGL_WARN, "%s failed", "FcStrSetAdd");
+                    ass_msg(library, MSGL_WARN, "%s failed", "FcStrSetAdd");
                     goto ErrorFontCache;
                 }
 
@@ -483,13 +486,13 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
                                FcConfigGetBlanks(priv->config),
                                (const FcChar8 *) dir, FcFalse);
                 if (!rc) {
-                    ass_msg(MSGL_WARN, "%s failed", "FcDirScan");
+                    ass_msg(library, MSGL_WARN, "%s failed", "FcDirScan");
                     goto ErrorFontCache;
                 }
 
                 rc = FcDirSave(fcs, fss, (const FcChar8 *) dir);
                 if (!rc) {
-                    ass_msg(MSGL_WARN, "%s failed", "FcDirSave");
+                    ass_msg(library, MSGL_WARN, "%s failed", "FcDirSave");
                     goto ErrorFontCache;
                 }
               ErrorFontCache:
@@ -499,7 +502,7 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
 
         rc = FcConfigAppFontAddDir(priv->config, (const FcChar8 *) dir);
         if (!rc) {
-            ass_msg(MSGL_WARN, "%s failed", "FcConfigAppFontAddDir");
+            ass_msg(library, MSGL_WARN, "%s failed", "FcConfigAppFontAddDir");
         }
     }
 
@@ -527,7 +530,7 @@ fc_instance_t *fontconfig_init(ass_library_t *library,
 {
     fc_instance_t *priv;
 
-    ass_msg(MSGL_WARN,
+    ass_msg(library, MSGL_WARN,
         "Fontconfig disabled, only default font will be used.");
 
     priv = calloc(1, sizeof(fc_instance_t));
index 71b2006b03323fcfabee9be8c73eb23ed45793c3..53441cce674f579458810771dd84fe9f40b45acb 100644 (file)
@@ -35,9 +35,10 @@ typedef struct fc_instance_s fc_instance_t;
 fc_instance_t *fontconfig_init(ass_library_t *library,
                                FT_Library ftlibrary, const char *family,
                                const char *path, int fc, const char *config);
-char *fontconfig_select(fc_instance_t *priv, const char *family,
-                        int treat_family_as_pattern, unsigned bold,
-                        unsigned italic, int *index, uint32_t code);
+char *fontconfig_select(ass_library_t *library, fc_instance_t *priv,
+                        const char *family, int treat_family_as_pattern,
+                        unsigned bold, unsigned italic, int *index,
+                        uint32_t code);
 void fontconfig_done(fc_instance_t *priv);
 
 #endif                          /* LIBASS_FONTCONFIG_H */
index ce877da7e056e0aa0ced11eda68fc95fb267c9d0..2a8f5b25164fb7783e0135b0bd5c8745813dbdd4 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
 
 #include "ass.h"
 #include "ass_library.h"
+#include "ass_utils.h"
 
+static void ass_msg_handler(int level, char *fmt, va_list *va)
+{
+    if (level > MSGL_INFO)
+        return;
+    printf("[ass] "); 
+    vprintf(fmt, *va);
+    printf("\n");
+}
 
 ass_library_t *ass_library_init(void)
 {
-    return calloc(1, sizeof(ass_library_t));
+    ass_library_t* lib = calloc(1, sizeof(ass_library_t));
+    lib->msg_callback = ass_msg_handler;
+
+    return lib;
 }
 
 void ass_library_done(ass_library_t *priv)
@@ -114,3 +127,16 @@ void ass_clear_fonts(ass_library_t *priv)
     priv->fontdata = NULL;
     priv->num_fontdata = 0;
 }
+
+/*
+ * Register a message callback function with libass.  Without setting one,
+ * a default handler is used which prints everything with MSGL_INFO or
+ * higher to the standard output.
+ */
+void ass_set_message_cb(ass_library_t *priv,
+                        void (*msg_cb)(int, char *, va_list *))
+{
+    if (msg_cb)
+        priv->msg_callback = msg_cb;
+}
+
index 48ffefe8b1a6ff11cfd1d6ade1802b409f4ce58f..a73dd6c0d745f959903436576e79006a2629d044 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef LIBASS_LIBRARY_H
 #define LIBASS_LIBRARY_H
 
+#include <stdarg.h>
+
 typedef struct ass_fontdata_s {
     char *name;
     char *data;
@@ -34,6 +36,7 @@ struct ass_library_s {
 
     ass_fontdata_t *fontdata;
     int num_fontdata;
+    void (*msg_callback)(int, char *, va_list *);
 };
 
 #endif                          /* LIBASS_LIBRARY_H */
index c5d7d06e6cf7d9db892350b2e74f8662e0d3ebc8..ccd7bd57c88c1194389190cc30830ccdbc556222 100644 (file)
@@ -245,7 +245,7 @@ static void ass_lazy_track_init(ass_renderer_t *render_priv)
     if (track->PlayResX && track->PlayResY)
         return;
     if (!track->PlayResX && !track->PlayResY) {
-        ass_msg(MSGL_WARN,
+        ass_msg(render_priv->library, MSGL_WARN,
                "Neither PlayResX nor PlayResY defined. Assuming 384x288");
         track->PlayResX = 384;
         track->PlayResY = 288;
@@ -256,19 +256,19 @@ static void ass_lazy_track_init(ass_renderer_t *render_priv)
             render_priv->width;
         if (!track->PlayResY && track->PlayResX == 1280) {
             track->PlayResY = 1024;
-            ass_msg(MSGL_WARN,
+            ass_msg(render_priv->library, MSGL_WARN,
                    "PlayResY undefined, setting to %d", track->PlayResY);
         } else if (!track->PlayResY) {
             track->PlayResY = track->PlayResX / orig_aspect + .5;
-            ass_msg(MSGL_WARN,
+            ass_msg(render_priv->library, MSGL_WARN,
                    "PlayResY undefined, setting to %d", track->PlayResY);
         } else if (!track->PlayResX && track->PlayResY == 1024) {
             track->PlayResX = 1280;
-            ass_msg(MSGL_WARN,
+            ass_msg(render_priv->library, MSGL_WARN,
                    "PlayResX undefined, setting to %d", track->PlayResX);
         } else if (!track->PlayResX) {
             track->PlayResX = track->PlayResY * orig_aspect + .5;
-            ass_msg(MSGL_WARN,
+            ass_msg(render_priv->library, MSGL_WARN,
                    "PlayResX undefined, setting to %d", track->PlayResX);
         }
     }
@@ -283,14 +283,14 @@ ass_renderer_t *ass_renderer_init(ass_library_t *library)
 
     error = FT_Init_FreeType(&ft);
     if (error) {
-        ass_msg(MSGL_FATAL, "%s failed", "FT_Init_FreeType");
+        ass_msg(library, MSGL_FATAL, "%s failed", "FT_Init_FreeType");
         goto ass_init_exit;
     }
 
     FT_Library_Version(ft, &vmajor, &vminor, &vpatch);
-    ass_msg(MSGL_V, "FreeType library version: %d.%d.%d",
+    ass_msg(library, MSGL_V, "FreeType library version: %d.%d.%d",
            vmajor, vminor, vpatch);
-    ass_msg(MSGL_V, "FreeType headers version: %d.%d.%d",
+    ass_msg(library, MSGL_V, "FreeType headers version: %d.%d.%d",
            FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
 
     priv = calloc(1, sizeof(ass_renderer_t));
@@ -305,10 +305,10 @@ ass_renderer_t *ass_renderer_init(ass_library_t *library)
     priv->ftlibrary = ft;
     // images_root and related stuff is zero-filled in calloc
 
-    priv->cache.font_cache = ass_font_cache_init();
-    priv->cache.bitmap_cache = ass_bitmap_cache_init();
-    priv->cache.composite_cache = ass_composite_cache_init();
-    priv->cache.glyph_cache = ass_glyph_cache_init();
+    priv->cache.font_cache = ass_font_cache_init(library);
+    priv->cache.bitmap_cache = ass_bitmap_cache_init(library);
+    priv->cache.composite_cache = ass_composite_cache_init(library);
+    priv->cache.glyph_cache = ass_glyph_cache_init(library);
 
     priv->text_info.max_glyphs = MAX_GLYPHS_INITIAL;
     priv->text_info.max_lines = MAX_LINES_INITIAL;
@@ -318,9 +318,9 @@ ass_renderer_t *ass_renderer_init(ass_library_t *library)
 
   ass_init_exit:
     if (priv)
-        ass_msg(MSGL_INFO, "Init");
+        ass_msg(library, MSGL_INFO, "Init");
     else
-        ass_msg(MSGL_ERR, "Init failed");
+        ass_msg(library, MSGL_ERR, "Init failed");
 
     return priv;
 }
@@ -527,22 +527,22 @@ static ass_image_t **render_glyph(ass_renderer_t *render_priv,
 
     tmp = dst_x - clip_x0;
     if (tmp < 0) {
-        ass_msg(MSGL_DBG2, "clip left");
+        ass_msg(render_priv->library, MSGL_DBG2, "clip left");
         b_x0 = -tmp;
     }
     tmp = dst_y - clip_y0;
     if (tmp < 0) {
-        ass_msg(MSGL_DBG2, "clip top");
+        ass_msg(render_priv->library, MSGL_DBG2, "clip top");
         b_y0 = -tmp;
     }
     tmp = clip_x1 - dst_x - bm->w;
     if (tmp < 0) {
-        ass_msg(MSGL_DBG2, "clip right");
+        ass_msg(render_priv->library, MSGL_DBG2, "clip right");
         b_x1 = bm->w + tmp;
     }
     tmp = clip_y1 - dst_y - bm->h;
     if (tmp < 0) {
-        ass_msg(MSGL_DBG2, "clip bottom");
+        ass_msg(render_priv->library, MSGL_DBG2, "clip bottom");
         b_y1 = bm->h + tmp;
     }
 
@@ -939,7 +939,8 @@ static void change_border(ass_renderer_t *render_priv, double border_x,
                                memory, &render_priv->state.stroker);
 #endif
             if (error) {
-                ass_msg(MSGL_V, "failed to get stroker");
+                ass_msg(render_priv->library, MSGL_V,
+                        "failed to get stroker");
                 render_priv->state.stroker = 0;
             }
         }
@@ -1172,14 +1173,14 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
             mystrtoll(&p, &t1);
             skip(',');
             mystrtoll(&p, &t2);
-            ass_msg(MSGL_DBG2,
+            ass_msg(render_priv->library, MSGL_DBG2,
                    "movement6: (%f, %f) -> (%f, %f), (%" PRId64 " .. %"
                    PRId64 ")\n", x1, y1, x2, y2, (int64_t) t1,
                    (int64_t) t2);
         } else {
             t1 = 0;
             t2 = render_priv->state.event->Duration;
-            ass_msg(MSGL_DBG2,
+            ass_msg(render_priv->library, MSGL_DBG2,
                    "movement: (%f, %f) -> (%f, %f)", x1, y1, x2, y2);
         }
         skip(')');
@@ -1241,7 +1242,7 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
     } else if (mystrcmp(&p, "alpha")) {
         uint32_t val;
         int i;
-        if (strtocolor(&p, &val)) {
+        if (strtocolor(render_priv->library, &p, &val)) {
             unsigned char a = val >> 24;
             for (i = 0; i < 4; ++i)
                 change_alpha(&render_priv->state.c[i], a, pwr);
@@ -1260,12 +1261,12 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
         int val;
         if (mystrtoi(&p, &val) && val) {
             int v = (val - 1) / 3;      // 0, 1 or 2 for vertical alignment
-            ass_msg(MSGL_DBG2, "an %d", val);
+            ass_msg(render_priv->library, MSGL_DBG2, "an %d", val);
             if (v != 0)
                 v = 3 - v;
             val = ((val - 1) % 3) + 1;  // horizontal alignment
             val += v * 4;
-            ass_msg(MSGL_DBG2, "align %d", val);
+            ass_msg(render_priv->library, MSGL_DBG2, "align %d", val);
             render_priv->state.alignment = val;
         } else
             render_priv->state.alignment =
@@ -1284,9 +1285,9 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
         skip(',');
         mystrtod(&p, &v2);
         skip(')');
-        ass_msg(MSGL_DBG2, "pos(%f, %f)", v1, v2);
+        ass_msg(render_priv->library, MSGL_DBG2, "pos(%f, %f)", v1, v2);
         if (render_priv->state.evt_type == EVENT_POSITIONED) {
-            ass_msg(MSGL_V, "Subtitle has a new \\pos "
+            ass_msg(render_priv->library, MSGL_V, "Subtitle has a new \\pos "
                    "after \\move or \\pos, ignoring");
         } else {
             render_priv->state.evt_type = EVENT_POSITIONED;
@@ -1339,7 +1340,7 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
         skip(',');
         mystrtoi(&p, &v2);
         skip(')');
-        ass_msg(MSGL_DBG2, "org(%d, %d)", v1, v2);
+        ass_msg(render_priv->library, MSGL_DBG2, "org(%d, %d)", v1, v2);
         if (!render_priv->state.have_origin) {
             render_priv->state.org_x = v1;
             render_priv->state.org_y = v2;
@@ -1425,9 +1426,9 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
         }
     } else if (mystrcmp(&p, "c")) {
         uint32_t val;
-        if (!strtocolor(&p, &val))
+        if (!strtocolor(render_priv->library, &p, &val))
             val = render_priv->state.style->PrimaryColour;
-        ass_msg(MSGL_DBG2, "color: %X", val);
+        ass_msg(render_priv->library, MSGL_DBG2, "color: %X", val);
         change_color(&render_priv->state.c[0], val, pwr);
     } else if ((*p >= '1') && (*p <= '4') && (++p)
                && (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) {
@@ -1436,7 +1437,7 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
         char cmd = *(p - 1);
         uint32_t val;
         assert((n >= '1') && (n <= '4'));
-        if (!strtocolor(&p, &val))
+        if (!strtocolor(render_priv->library, &p, &val))
             switch (n) {
             case '1':
                 val = render_priv->state.style->PrimaryColour;
@@ -1462,10 +1463,11 @@ static char *parse_tag(ass_renderer_t *render_priv, char *p, double pwr)
             change_alpha(render_priv->state.c + cidx, val >> 24, pwr);
             break;
         default:
-            ass_msg(MSGL_WARN, "Bad command: %c%c", n, cmd);
+            ass_msg(render_priv->library, MSGL_WARN, "Bad command: %c%c",
+                    n, cmd);
             break;
         }
-        ass_msg(MSGL_DBG2, "single c/a at %f: %c%c = %X",
+        ass_msg(render_priv->library, MSGL_DBG2, "single c/a at %f: %c%c = %X",
                pwr, n, cmd, render_priv->state.c[cidx]);
     } else if (mystrcmp(&p, "r")) {
         reset_render_context(render_priv);
@@ -1579,7 +1581,8 @@ static unsigned get_next_char(ass_renderer_t *render_priv, char **str)
                 } else
                     break;
             } else if (*p != '\\')
-                ass_msg(MSGL_V, "Unable to parse: '%s'", p);
+                ass_msg(render_priv->library, MSGL_V,
+                        "Unable to parse: '%s'", p);
             if (*p == 0)
                 break;
         }
@@ -1625,8 +1628,8 @@ apply_transition_effects(ass_renderer_t *render_priv, ass_event_t *event)
     if (strncmp(event->Effect, "Banner;", 7) == 0) {
         int delay;
         if (cnt < 1) {
-            ass_msg(MSGL_V, "Error parsing effect: '%s'",
-                   event->Effect);
+            ass_msg(render_priv->library, MSGL_V,
+                    "Error parsing effect: '%s'", event->Effect);
             return;
         }
         if (cnt >= 2 && v[1] == 0)      // right-to-left
@@ -1648,8 +1651,8 @@ apply_transition_effects(ass_renderer_t *render_priv, ass_event_t *event)
     } else if (strncmp(event->Effect, "Scroll down;", 12) == 0) {
         render_priv->state.scroll_direction = SCROLL_TB;
     } else {
-        ass_msg(MSGL_V, "Unknown transition effect: '%s'",
-               event->Effect);
+        ass_msg(render_priv->library, MSGL_V,
+                "Unknown transition effect: '%s'", event->Effect);
         return;
     }
     // parse scroll up/down parameters
@@ -1657,8 +1660,8 @@ apply_transition_effects(ass_renderer_t *render_priv, ass_event_t *event)
         int delay;
         int y0, y1;
         if (cnt < 3) {
-            ass_msg(MSGL_V, "Error parsing effect: '%s'",
-                   event->Effect);
+            ass_msg(render_priv->library, MSGL_V,
+                    "Error parsing effect: '%s'", event->Effect);
             return;
         }
         delay = v[2];
@@ -1864,7 +1867,8 @@ static void stroke_outline_glyph(ass_renderer_t *render_priv,
         error = FT_Glyph_StrokeBorder((FT_Glyph *) glyph,
                                       render_priv->state.stroker, 0, 1);
         if (error)
-            ass_msg(MSGL_WARN, "FT_Glyph_Stroke error: %d", error);
+            ass_msg(render_priv->library, MSGL_WARN,
+                    "FT_Glyph_Stroke error: %d", error);
 
     // "Stroke" with the outline emboldener in two passes.
     // The outlines look uglier, but the emboldening never adds any points
@@ -2036,7 +2040,8 @@ get_bitmap_glyph(ass_renderer_t *render_priv, glyph_info_t *info)
                     -info->hash_key.advance.y);
 
             // render glyph
-            error = glyph_to_bitmap(render_priv->synth_priv,
+            error = glyph_to_bitmap(render_priv->library,
+                                    render_priv->synth_priv,
                                     info->glyph, info->outline_glyph,
                                     &info->bm, &info->bm_o,
                                     &info->bm_s, info->be,
@@ -2133,8 +2138,8 @@ wrap_lines_smart(ass_renderer_t *render_priv, double max_text_width)
         if (cur->symbol == '\n') {
             break_type = 2;
             break_at = i;
-            ass_msg(MSGL_DBG2, "forced line break at %d",
-                   break_at);
+            ass_msg(render_priv->library, MSGL_DBG2,
+                    "forced line break at %d", break_at);
         }
 
         if ((len >= max_text_width)
@@ -2145,8 +2150,9 @@ wrap_lines_smart(ass_renderer_t *render_priv, double max_text_width)
                 break_at = i - 1;
             if (break_at == -1)
                 break_at = 0;
-            ass_msg(MSGL_DBG2, "overfill at %d", i);
-            ass_msg(MSGL_DBG2, "line break at %d", break_at);
+            ass_msg(render_priv->library, MSGL_DBG2, "overfill at %d", i);
+            ass_msg(render_priv->library, MSGL_DBG2, "line break at %d",
+                    break_at);
         }
 
         if (break_at != -1) {
@@ -2245,7 +2251,7 @@ wrap_lines_smart(ass_renderer_t *render_priv, double max_text_width)
             cur_line++;
             pen_shift_x = d6_to_double(-cur->pos.x);
             pen_shift_y += height + render_priv->settings.line_spacing;
-            ass_msg(MSGL_DBG2,
+            ass_msg(render_priv->library, MSGL_DBG2,
                    "shifting from %d to %d by (%f, %f)", i,
                    text_info->length - 1, pen_shift_x, pen_shift_y);
         }
@@ -2310,7 +2316,8 @@ static void process_karaoke_effects(ass_renderer_t *render_priv)
                     dt /= (tm_end - tm_start);
                     x = x_start + (x_end - x_start) * dt;
                 } else {
-                    ass_msg(MSGL_ERR, "Unknown effect type");
+                    ass_msg(render_priv->library, MSGL_ERR,
+                            "Unknown effect type");
                     continue;
                 }
 
@@ -2463,11 +2470,11 @@ ass_render_event(ass_renderer_t *render_priv, ass_event_t *event,
     ass_drawing_t *drawing;
 
     if (event->Style >= render_priv->track->n_styles) {
-        ass_msg(MSGL_WARN, "No style found");
+        ass_msg(render_priv->library, MSGL_WARN, "No style found");
         return 1;
     }
     if (!event->Text) {
-        ass_msg(MSGL_WARN, "Empty event");
+        ass_msg(render_priv->library, MSGL_WARN, "Empty event");
         return 1;
     }
 
@@ -2767,7 +2774,7 @@ ass_render_event(ass_renderer_t *render_priv, ass_event_t *event,
         } else {                // subtitle
             double scr_y;
             if (valign != VALIGN_SUB)
-                ass_msg(MSGL_V,
+                ass_msg(render_priv->library, MSGL_V,
                        "Invalid valign, supposing 0 (subtitle)");
             scr_y =
                 y2scr_sub(render_priv,
@@ -2793,7 +2800,7 @@ ass_render_event(ass_renderer_t *render_priv, ass_event_t *event,
     if (render_priv->state.evt_type == EVENT_POSITIONED) {
         double base_x = 0;
         double base_y = 0;
-        ass_msg(MSGL_DBG2, "positioned event at %f, %f",
+        ass_msg(render_priv->library, MSGL_DBG2, "positioned event at %f, %f",
                render_priv->state.pos_x, render_priv->state.pos_y);
         get_base_point(&bbox, alignment, &base_x, &base_y);
         device_x =
@@ -3174,7 +3181,8 @@ fix_collisions(ass_renderer_t *render_priv, event_images_t *imgs, int cnt)
             s.a = priv->top;
             s.b = priv->top + priv->height;
             if (priv->height != imgs[i].height) {       // no, it's not
-                ass_msg(MSGL_WARN, "Warning! Event height has changed");
+                ass_msg(render_priv->library, MSGL_WARN,
+                        "Warning! Event height has changed");
                 priv->top = 0;
                 priv->height = 0;
             }
index 6e45b022352000e61927deaf5f693d8e02ceda04..0592d33e65a3baccc5f5f148f4b5d69e5a641885 100644 (file)
 #include "config.h"
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <inttypes.h>
 #include <ft2build.h>
 #include FT_GLYPH_H
 
+#include "ass_library.h"
+#include "ass.h"
 #include "ass_utils.h"
 
 int mystrtoi(char **p, int *res)
@@ -71,7 +74,7 @@ int mystrtod(char **p, double *res)
         return 0;
 }
 
-int strtocolor(char **q, uint32_t *res)
+int strtocolor(ass_library_t *library, char **q, uint32_t *res)
 {
     uint32_t color = 0;
     int result;
@@ -80,7 +83,7 @@ int strtocolor(char **q, uint32_t *res)
     if (*p == '&')
         ++p;
     else
-        ass_msg(MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
+        ass_msg(library, MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
 
     if (*p == 'H' || *p == 'h') {
         ++p;
@@ -119,15 +122,11 @@ char parse_bool(char *str)
     return 0;
 }
 
-void ass_msg(int lvl, char *fmt, ...)
+void ass_msg(ass_library_t *priv, int lvl, char *fmt, ...)
 {
     va_list va;
-    if (lvl > MSGL_INFO)
-        return;
     va_start(va, fmt);
-    printf("[ass] ");
-    vprintf(fmt, va);
-    printf("\n");
+    priv->msg_callback(lvl, fmt, &va);
     va_end(va);
 }
 
@@ -162,8 +161,9 @@ unsigned ass_utf8_get_char(char **str)
 }
 
 #ifdef CONFIG_ENCA
-void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
-                      char *preferred_language, char *fallback)
+void *ass_guess_buffer_cp(ass_library_t *library, unsigned char *buffer,
+                          int buflen, char *preferred_language,
+                          char *fallback)
 {
     const char **languages;
     size_t langcnt;
@@ -173,11 +173,10 @@ void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
     int i;
 
     languages = enca_get_languages(&langcnt);
-    ass_msg(MSGL_V, "ENCA supported languages: ");
+    ass_msg(library, MSGL_V, "ENCA supported languages");
     for (i = 0; i < langcnt; i++) {
-        ass_msg(MSGL_V, "%s ", languages[i]);
+        ass_msg(library, MSGL_V, "lang %s", languages[i]);
     }
-    ass_msg(MSGL_V, "\n");
 
     for (i = 0; i < langcnt; i++) {
         const char *tmp;
@@ -189,7 +188,7 @@ void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
         tmp = enca_charset_name(encoding.charset, ENCA_NAME_STYLE_ICONV);
         if (tmp && encoding.charset != ENCA_CS_UNKNOWN) {
             detected_sub_cp = strdup(tmp);
-            ass_msg(MSGL_INFO, "ENCA detected charset: %s\n", tmp);
+            ass_msg(library, MSGL_INFO, "ENCA detected charset: %s", tmp);
         }
         enca_analyser_free(analyser);
     }
@@ -198,8 +197,8 @@ void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
 
     if (!detected_sub_cp) {
         detected_sub_cp = strdup(fallback);
-        ass_msg(MSGL_INFO,
-               "ENCA detection failed: fallback to %s\n", fallback);
+        ass_msg(library, MSGL_INFO,
+               "ENCA detection failed: fallback to %s", fallback);
     }
 
     return detected_sub_cp;
index efcf88345257a9c15e7e103cf540cbb86b586e40..a906ca57ae7eb38e01bc46cd87852030c2e27c2b 100644 (file)
@@ -32,6 +32,8 @@
 #include <enca.h>
 #endif
 
+#include "ass.h"
+
 #define MSGL_FATAL 0
 #define MSGL_ERR 1
 #define MSGL_WARN 2
@@ -46,12 +48,15 @@ int mystrtoi(char **p, int *res);
 int mystrtoll(char **p, long long *res);
 int mystrtou32(char **p, int base, uint32_t *res);
 int mystrtod(char **p, double *res);
-int strtocolor(char **q, uint32_t *res);
+int strtocolor(ass_library_t *library, char **q, uint32_t *res);
 char parse_bool(char *str);
 unsigned ass_utf8_get_char(char **str);
-void ass_msg(int lvl, char *fmt, ...);
-void *ass_guess_buffer_cp(unsigned char *buffer, int buflen,
-                          char *preferred_language, char *fallback);
+void ass_msg(ass_library_t *priv, int lvl, char *fmt, ...);
+#ifdef CONFIG_ENCA
+void *ass_guess_buffer_cp(ass_library_t *library, unsigned char *buffer,
+                          int buflen, char *preferred_language,
+                          char *fallback);
+#endif
 
 static inline int d6_to_int(int x)
 {
index 7579b4f9eb20f65b12de8b6125dac7af4fe4b3a9..5cb1c40a4b79c67aeeb50c440e2d1860302c142c 100644 (file)
@@ -30,3 +30,4 @@ ass_add_font
 ass_clear_fonts
 ass_step_sub
 ass_process_force_style
+ass_set_message_cb
index 816d7791c31b703bb7873f1307a0224816980cf0..9728590a4d71615ab67ce3784f7386aeda6959ee 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdexcept>
+#include <stdarg.h>
 
 extern "C" {
 #include <ass.h>
@@ -16,6 +17,15 @@ struct image_t {
 ass_library_t* ass_library;
 ass_renderer_t* ass_renderer;
 
+void msg_callback(int level, char *fmt, va_list *va)
+{
+    if (level > 6)
+        return;
+    printf("libass: ");
+    vprintf(fmt, *va);
+    printf("\n");
+}
+
 static void write_png(char *fname, image_t* img)
 {
     FILE * fp;
@@ -71,6 +81,7 @@ static void init(int frame_w, int frame_h) {
   ass_set_fonts_dir(ass_library, "");
   ass_set_extract_fonts(ass_library, 0);
   ass_set_style_overrides(ass_library, NULL);
+  ass_set_message_cb(ass_library, msg_callback);
 
   ass_renderer = ass_renderer_init(ass_library);
   if (!ass_renderer) throw std::runtime_error("ass_renderer_init failed");