[vlc-commits] [Git][videolan/vlc][master] 5 commits: json: add getter functions to the json API

Steve Lhomme (@robUx4) gitlab at videolan.org
Sun Oct 6 07:50:37 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
7e5d3b86 by Gabriel Lafond-Thenaille at 2024-10-06T07:34:42+00:00
json: add getter functions to the json API

Add wrapper functions arround json_get for json arrays and objects.

Co-authored-by: Mehdi Sabwat <mehdi at videolabs.io>

- - - - -
b7620213 by Gabriel Lafond-Thenaille at 2024-10-06T07:34:42+00:00
meson: make the json parser available as a static library in meson

- - - - -
5002a695 by Gabriel Lafond-Thenaille at 2024-10-06T07:34:42+00:00
webservices: use demux/json parser in webservices

Co-authored-by: Mehdi Sabwat <mehdi at videolabs.io>

- - - - -
d85ecc2d by Gabriel Lafond-Thenaille at 2024-10-06T07:34:42+00:00
chromecast: use demux/json parser in chromecast

Co-authored-by: Mehdi Sabwat <mehdi at videolabs.io>

- - - - -
5cb606cf by Gabriel Lafond-Thenaille at 2024-10-06T07:34:42+00:00
json: remove webservices json parser implementation

- - - - -


19 changed files:

- modules/access/Makefile.am
- modules/access/meson.build
- modules/demux/Makefile.am
- modules/demux/json/grammar.y
- modules/demux/json/json.c
- modules/demux/json/json.h
- modules/demux/json/lexicon.l
- modules/meson.build
- modules/misc/Makefile.am
- modules/misc/meson.build
- modules/misc/webservices/acoustid.c
- − modules/misc/webservices/json.c
- − modules/misc/webservices/json.h
- modules/misc/webservices/json_helper.h
- modules/misc/webservices/musicbrainz.c
- modules/stream_out/Makefile.am
- modules/stream_out/chromecast/chromecast.h
- modules/stream_out/chromecast/chromecast_ctrl.cpp
- modules/stream_out/chromecast/meson.build


Changes:

=====================================
modules/access/Makefile.am
=====================================
@@ -236,11 +236,11 @@ EXTRA_LTLIBRARIES += libvnc_plugin.la
 ### Optical media ###
 
 libcdda_plugin_la_SOURCES = access/cdda.c access/disc_helper.h access/vcd/cdrom.c access/vcd/cdrom.h \
-                            access/vcd/cdrom_internals.h misc/webservices/json.c misc/webservices/json.h \
+                            access/vcd/cdrom_internals.h \
                             misc/webservices/json_helper.h misc/webservices/musicbrainz.c \
                             misc/webservices/musicbrainz.h
 libcdda_plugin_la_CFLAGS = $(AM_CFLAGS) $(LIBCDDB_CFLAGS)
-libcdda_plugin_la_LIBADD = $(LIBCDDB_LIBS) $(LIBM)
+libcdda_plugin_la_LIBADD = libvlc_json.la $(LIBCDDB_LIBS) $(LIBM)
 libcdda_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
 if HAVE_DARWIN
 libcdda_plugin_la_LIBADD += -liconv


=====================================
modules/access/meson.build
=====================================
@@ -202,6 +202,7 @@ endif
 
 
 ## Optical media
+#
 
 # VCD and CD-DA access module
 if get_option('vcd_module')
@@ -238,10 +239,10 @@ if get_option('vcd_module')
             'sources' : files(
                 'cdda.c',
                 'vcd/cdrom.c',
-                '../misc/webservices/json.c',
                 '../misc/webservices/musicbrainz.c',
             ),
             'c_args' : vcd_cdda_flags,
+            'link_with' : vlc_json_lib,
             'dependencies' : [libcddb_dep, vcd_cdda_darwin_deps]
         }
 


=====================================
modules/demux/Makefile.am
=====================================
@@ -558,4 +558,5 @@ libvlc_json_la_SOURCES = \
 libvlc_json_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/demux/json
 libvlc_json_la_LIBADD = $(LTLIBVLCCORE) ../compat/libcompat.la $(LIBM)
 libvlc_json_la_LDFLAGS = -static
+libvlc_json_la_LFLAGS = $(AM_LFLAGS) --outfile=lex.yy.c
 noinst_LTLIBRARIES += libvlc_json.la


=====================================
modules/demux/json/grammar.y
=====================================
@@ -22,7 +22,7 @@
 %define api.prefix {json}
 
 %lex-param { void *scanner }
-%parse-param { void *log }
+%parse-param { void *opaque }
 %parse-param { void *scanner }
 %parse-param { struct json_object *result }
 
@@ -144,14 +144,14 @@ static void json_append(struct json_object *o, struct json_member m)
 
 %{
 
-static void yyerror(void *log, void *scanner, struct json_object *result,
-			const char *msg)
+static void yyerror(void *opaque, void *scanner, struct json_object *result,
+                    const char *msg)
 {
-	json_parse_error(log, msg);
+	json_parse_error(opaque, msg);
 	(void) scanner; (void) result;
 }
 
-extern int jsonlex_init_extra(void *, void **);
+extern int jsonlex_init_extra(const void *, void **);
 extern int yylex(YYSTYPE *value, void *scanner);
 extern int jsonlex_destroy(void *);
 


=====================================
modules/demux/json/json.c
=====================================
@@ -134,6 +134,21 @@ const struct json_value *json_get(const struct json_object *obj,
     return NULL;
 }
 
+const struct json_object *json_get_object(const struct json_object *obj,
+                                          const char *name)
+{
+    const struct json_value *v = json_get(obj, name);
+    return (v != NULL && v->type == JSON_OBJECT) ? &v->object : NULL;
+}
+
+const struct json_array *json_get_array(const struct json_object *obj,
+                                 const char *name)
+{
+    const struct json_value *v = json_get(obj, name);
+    return (v != NULL && v->type == JSON_ARRAY) ? &v->array : NULL;
+}
+
+
 const char *json_get_str(const struct json_object *obj, const char *name)
 {
     const struct json_value *v = json_get(obj, name);


=====================================
modules/demux/json/json.h
=====================================
@@ -61,15 +61,19 @@ struct json_member {
     struct json_value value;
 };
 
-size_t json_read(void *data, void *buf, size_t max);
-void json_parse_error(void *log, const char *msg);
+size_t json_read(void *opaque, void *buf, size_t max);
+void json_parse_error(void *opaque, const char *msg);
 char *json_unescape(const char *, size_t);
 
-int json_parse(void *log, struct json_object *result);
+int json_parse(void *opaque, struct json_object *result);
 void json_free(struct json_object *);
 
 const struct json_value *json_get(const struct json_object *obj,
                                   const char *name);
+const struct json_object *json_get_object(const struct json_object *obj,
+                                          const char *name);
+const struct json_array *json_get_array(const struct json_object *obj,
+                                 const char *name);
 const char *json_get_str(const struct json_object *obj, const char *name);
 double json_get_num(const struct json_object *obj, const char *name);
 


=====================================
modules/demux/json/lexicon.l
=====================================
@@ -26,7 +26,7 @@
 %option nostdinit
 %option nounput
 %option noyywrap
-%option prefix="json" outfile="lex.yy.c"
+%option prefix="json"
 
 %{
 


=====================================
modules/meson.build
=====================================
@@ -201,6 +201,21 @@ libgcrypt_dep = dependency('libgcrypt',
 # Rust support
 cargo_bin = find_program('cargo', required: get_option('rust'))
 
+# JSON library
+json_bison_files = bison_gen.process('demux/json/grammar.y')
+json_lex_files = flex_gen.process('demux/json/lexicon.l')
+
+vlc_json_lib = static_library('vlc_json',
+    sources: [
+      json_bison_files,
+      json_lex_files,
+      'demux/json/json.c',
+    ],
+    include_directories: [vlc_include_dirs, 'demux/json/'],
+    install: false,
+    pic: true
+)
+
 # Array that holds all enabled VLC module dicts
 vlc_modules = []
 vlc_rust_modules = []


=====================================
modules/misc/Makefile.am
=====================================
@@ -17,11 +17,10 @@ misc_LTLIBRARIES += libexport_plugin.la
 
 libfingerprinter_plugin_la_SOURCES =  \
 	misc/webservices/acoustid.c misc/webservices/acoustid.h \
-	misc/webservices/json.c misc/webservices/json.h \
         misc/webservices/json_helper.h \
 	misc/fingerprinter.c
 libfingerprinter_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/misc
-libfingerprinter_plugin_la_LIBADD = $(LIBM)
+libfingerprinter_plugin_la_LIBADD = libvlc_json.la $(LIBM)
 misc_LTLIBRARIES += libfingerprinter_plugin.la
 
 libgnutls_plugin_la_SOURCES = misc/gnutls.c


=====================================
modules/misc/meson.build
=====================================
@@ -27,10 +27,10 @@ vlc_modules += {
     'name' : 'fingerprinter',
     'sources' : files(
         'fingerprinter.c',
-        'webservices/json.c',
         'webservices/acoustid.c',
     ),
-    'dependencies' : [m_lib]
+    'dependencies' : [m_lib],
+    'link_with' : vlc_json_lib,
 }
 
 # libxml2 module


=====================================
modules/misc/webservices/acoustid.c
=====================================
@@ -22,6 +22,9 @@
 # include "config.h"
 #endif
 
+#include <vlc_common.h>
+#include <vlc_messages.h>
+
 #include "json_helper.h"
 #include "acoustid.h"
 
@@ -39,36 +42,43 @@ void acoustid_result_release( acoustid_result_t * r )
     free( r->recordings.p_recordings );
 }
 
-static void parse_artists( const json_value *node, acoustid_mb_result_t *record )
+static void parse_artists( const struct json_array *artists, acoustid_mb_result_t *record )
 {
     /* take only main */
-    if ( !node || node->type != json_array || node->u.array.length < 1 )
+    if ( artists->size < 1)
         return;
-    record->psz_artist = json_dupstring( node->u.array.values[ 0 ], "name" );
+    if (artists->entries[0].type == JSON_OBJECT) {
+        record->psz_artist = json_dupstring( &artists->entries[ 0 ].object, "name" );
+    }
 }
 
-static void parse_recordings( vlc_object_t *p_obj, const json_value *node, acoustid_result_t *p_result )
+static void parse_recordings( vlc_object_t *p_obj, const struct json_object *object,
+                              acoustid_result_t *p_result )
 {
-    if ( !node || node->type != json_array ) return;
-    p_result->recordings.p_recordings = calloc( node->u.array.length, sizeof(acoustid_mb_result_t) );
+    const struct json_array *recordings = json_get_array(object, "recordings");
+    if (recordings == NULL)
+        return;
+    p_result->recordings.p_recordings = calloc( recordings->size, sizeof(acoustid_mb_result_t) );
     if ( ! p_result->recordings.p_recordings ) return;
-    p_result->recordings.count = node->u.array.length;
+    p_result->recordings.count = recordings->size;
 
-    for( unsigned int i=0; i<node->u.array.length; i++ )
+    for( unsigned int i = 0; i < recordings->size; i++ )
     {
         acoustid_mb_result_t *record = & p_result->recordings.p_recordings[ i ];
-        const json_value *recordnode = node->u.array.values[ i ];
-        if ( !recordnode || recordnode->type != json_object )
+        struct json_value *recordnode = &recordings->entries[ i ];
+        if ( recordnode->type != JSON_OBJECT )
             break;
-        record->psz_title = json_dupstring( recordnode, "title" );
-        const json_value *value = json_getbyname( recordnode, "id" );
-        if ( value && value->type == json_string )
+        record->psz_title = json_dupstring( &recordnode->object, "title" );
+        const char *id = json_get_str( &recordnode->object, "id" );
+        if ( id != NULL )
         {
-            size_t i_len = strlen( value->u.string.ptr );
+            size_t i_len = strlen( id );
             i_len = __MIN( i_len, MB_ID_SIZE );
-            memcpy( record->s_musicbrainz_id, value->u.string.ptr, i_len );
+            memcpy( record->s_musicbrainz_id, id, i_len );
         }
-        parse_artists( json_getbyname( recordnode, "artists" ), record );
+        const struct json_array *artists = json_get_array(&recordnode->object,
+                                                          "artists");
+        parse_artists( artists, record );
         msg_Dbg( p_obj, "recording %d title %s %36s %s", i, record->psz_title,
                  record->s_musicbrainz_id, record->psz_artist );
     }
@@ -77,49 +87,59 @@ static void parse_recordings( vlc_object_t *p_obj, const json_value *node, acous
 static bool ParseJson( vlc_object_t *p_obj, const void *p_buffer, size_t i_buffer,
                        acoustid_results_t *p_results )
 {
-    json_value *root = json_parse_document( p_obj, p_buffer, i_buffer );
-    if( !root )
+    struct json_helper_sys sys;
+    sys.logger = p_obj->logger;
+    sys.buffer = p_buffer;
+    sys.size = i_buffer;
+
+    struct json_object json;
+    int val = json_parse(&sys, &json);
+    if (val) {
+        msg_Dbg( p_obj, "error: could not parse json!");
         return false;
+    }
 
-    const json_value *node = json_getbyname( root, "status" );
-    if ( !node || node->type != json_string )
+    const char *status = json_get_str(&json, "status");
+    if (status == NULL)
     {
         msg_Warn( p_obj, "status node not found or invalid" );
-        goto error;
+        json_free(&json);
+        return false;
     }
-    if ( strcmp( node->u.string.ptr, "ok" ) != 0 )
+    if (strcmp(status, "ok") != 0)
     {
         msg_Warn( p_obj, "Bad request status" );
-        goto error;
+        json_free(&json);
+        return false;
     }
-    node = json_getbyname( root, "results" );
-    if ( !node || node->type != json_array )
+    const struct json_array *results = json_get_array(&json, "results");
+    if (results == NULL)
     {
         msg_Warn( p_obj, "Bad results array or no results" );
-        goto error;
+        json_free(&json);
+        return false;
     }
-    p_results->p_results = calloc( node->u.array.length, sizeof(acoustid_result_t) );
-    if ( ! p_results->p_results ) goto error;
-    p_results->count = node->u.array.length;
-    for( unsigned int i=0; i<node->u.array.length; i++ )
+    p_results->p_results = calloc(results->size, sizeof(acoustid_result_t));
+    if ( ! p_results->p_results ) {
+        json_free(&json);
+        return false;
+    }
+    p_results->count = results->size;
+    for( unsigned int i=0; i<results->size; i++ )
     {
-        const json_value *resultnode = node->u.array.values[i];
-        if ( resultnode && resultnode->type == json_object )
+        const struct json_value *resultnode = &results->entries[i];
+        if ( resultnode->type == JSON_OBJECT )
         {
             acoustid_result_t *p_result = & p_results->p_results[i];
-            const json_value *value = json_getbyname( resultnode, "score" );
-            if ( value && value->type == json_double )
-                p_result->d_score = value->u.dbl;
-            p_result->psz_id = json_dupstring( resultnode, "id" );
-            parse_recordings( p_obj, json_getbyname( resultnode, "recordings" ), p_result );
+            double score = json_get_num(&resultnode->object, "score");
+            if (score != NAN)
+                p_result->d_score = score;
+            p_result->psz_id = json_dupstring(&resultnode->object, "id");
+            parse_recordings( p_obj, &resultnode->object, p_result );
         }
     }
-    json_value_free( root );
+    json_free(&json);
     return true;
-
-error:
-    if ( root ) json_value_free( root );
-    return false;
 }
 
 int acoustid_lookup_fingerprint( const acoustid_config_t *p_cfg, acoustid_fingerprint_t *p_data )


=====================================
modules/misc/webservices/json.c deleted
=====================================
@@ -1,1005 +0,0 @@
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
- *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.
- * https://github.com/udp/json-parser
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "json.h"
-
-#ifdef _MSC_VER
-   #ifndef _CRT_SECURE_NO_WARNINGS
-      #define _CRT_SECURE_NO_WARNINGS
-   #endif
-#endif
-
-const struct _json_value json_value_none;
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-
-typedef unsigned int json_uchar;
-
-static unsigned char hex_value (json_char c)
-{
-   if (isdigit(c))
-      return c - '0';
-
-   switch (c) {
-      case 'a': case 'A': return 0x0A;
-      case 'b': case 'B': return 0x0B;
-      case 'c': case 'C': return 0x0C;
-      case 'd': case 'D': return 0x0D;
-      case 'e': case 'E': return 0x0E;
-      case 'f': case 'F': return 0x0F;
-      default: return 0xFF;
-   }
-}
-
-typedef struct
-{
-   unsigned long used_memory;
-
-   unsigned int uint_max;
-   unsigned long ulong_max;
-
-   json_settings settings;
-   int first_pass;
-
-   const json_char * ptr;
-   unsigned int cur_line, cur_col;
-
-} json_state;
-
-static void * default_alloc (size_t size, int zero, void * user_data)
-{
-   return zero ? calloc (1, size) : malloc (size);
-}
-
-static void default_free (void * ptr, void * user_data)
-{
-   free (ptr);
-}
-
-static void * json_alloc (json_state * state, unsigned long size, int zero)
-{
-   if ((state->ulong_max - state->used_memory) < size)
-      return 0;
-
-   if (state->settings.max_memory
-         && (state->used_memory += size) > state->settings.max_memory)
-   {
-      return 0;
-   }
-
-   return state->settings.mem_alloc (size, zero, state->settings.user_data);
-}
-
-static int new_value (json_state * state,
-                      json_value ** top, json_value ** root, json_value ** alloc,
-                      json_type type)
-{
-   json_value * value;
-   int values_size;
-
-   if (!state->first_pass)
-   {
-      value = *top = *alloc;
-      *alloc = (*alloc)->_reserved.next_alloc;
-
-      if (!*root)
-         *root = value;
-
-      switch (value->type)
-      {
-         case json_array:
-
-            if (! (value->u.array.values = (json_value **) json_alloc
-               (state, value->u.array.length * sizeof (json_value *), 0)) )
-            {
-               return 0;
-            }
-
-            value->u.array.length = 0;
-            break;
-
-         case json_object:
-
-            values_size = sizeof (*value->u.object.values) * value->u.object.length;
-
-            if (! ((*(void **) &value->u.object.values) = json_alloc
-                  (state, values_size + ((unsigned long) value->u.object.values), 0)) )
-            {
-               return 0;
-            }
-
-            value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
-
-            value->u.object.length = 0;
-            break;
-
-         case json_string:
-
-            if (! (value->u.string.ptr = (json_char *) json_alloc
-               (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
-            {
-               return 0;
-            }
-
-            value->u.string.length = 0;
-            break;
-
-         default:
-            break;
-      };
-
-      return 1;
-   }
-
-   if (! (value = (json_value *) json_alloc
-         (state, sizeof (json_value) + state->settings.value_extra, 1)))
-   {
-      return 0;
-   }
-
-   if (!*root)
-      *root = value;
-
-   value->type = type;
-   value->parent = *top;
-
-   #ifdef JSON_TRACK_SOURCE
-      value->line = state->cur_line;
-      value->col = state->cur_col;
-   #endif
-
-   if (*alloc)
-      (*alloc)->_reserved.next_alloc = value;
-
-   *alloc = *top = value;
-
-   return 1;
-}
-
-#define whitespace \
-   case '\n': ++ state.cur_line;  state.cur_col = 0; \
-   case ' ': case '\t': case '\r'
-
-#define string_add(b)  \
-   do { if (!state.first_pass) string [string_length] = b;  ++ string_length; } while (0);
-
-#define line_and_col \
-   state.cur_line, state.cur_col
-
-static const long
-   flag_next             = 1 << 0,
-   flag_reproc           = 1 << 1,
-   flag_need_comma       = 1 << 2,
-   flag_seek_value       = 1 << 3,
-   flag_escaped          = 1 << 4,
-   flag_string           = 1 << 5,
-   flag_need_colon       = 1 << 6,
-   flag_done             = 1 << 7,
-   flag_num_negative     = 1 << 8,
-   flag_num_zero         = 1 << 9,
-   flag_num_e            = 1 << 10,
-   flag_num_e_got_sign   = 1 << 11,
-   flag_num_e_negative   = 1 << 12,
-   flag_line_comment     = 1 << 13,
-   flag_block_comment    = 1 << 14;
-
-json_value * json_parse_ex (json_settings * settings,
-                            const json_char * json,
-                            size_t length,
-                            char * error_buf)
-{
-   json_char error [json_error_max];
-   const json_char * end;
-   json_value * top, * root, * alloc = 0;
-   json_state state = { 0 };
-   long flags;
-   long num_digits = 0, num_e = 0;
-   json_int_t num_fraction = 0;
-
-   /* Skip UTF-8 BOM
-    */
-   if (length >= 3 && ((unsigned char) json [0]) == 0xEF
-                   && ((unsigned char) json [1]) == 0xBB
-                   && ((unsigned char) json [2]) == 0xBF)
-   {
-      json += 3;
-      length -= 3;
-   }
-
-   error[0] = '\0';
-   end = (json + length);
-
-   memcpy (&state.settings, settings, sizeof (json_settings));
-
-   if (!state.settings.mem_alloc)
-      state.settings.mem_alloc = default_alloc;
-
-   if (!state.settings.mem_free)
-      state.settings.mem_free = default_free;
-
-   memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
-   memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
-
-   state.uint_max -= 8; /* limit of how much can be added before next check */
-   state.ulong_max -= 8;
-
-   for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
-   {
-      json_uchar uchar;
-      unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
-      json_char * string = 0;
-      unsigned int string_length = 0;
-
-      top = root = 0;
-      flags = flag_seek_value;
-
-      state.cur_line = 1;
-
-      for (state.ptr = json ;; ++ state.ptr)
-      {
-         json_char b = (state.ptr == end ? 0 : *state.ptr);
-
-         if (flags & flag_string)
-         {
-            if (!b)
-            {  sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
-               goto e_failed;
-            }
-
-            if (string_length > state.uint_max)
-               goto e_overflow;
-
-            if (flags & flag_escaped)
-            {
-               flags &= ~ flag_escaped;
-
-               switch (b)
-               {
-                  case 'b':  string_add ('\b');  break;
-                  case 'f':  string_add ('\f');  break;
-                  case 'n':  string_add ('\n');  break;
-                  case 'r':  string_add ('\r');  break;
-                  case 't':  string_add ('\t');  break;
-                  case 'u':
-
-                    if (end - state.ptr < 4 ||
-                        (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
-                        (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
-                        (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
-                        (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
-                    {
-                        sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
-                        goto e_failed;
-                    }
-
-                    uc_b1 = (uc_b1 << 4) | uc_b2;
-                    uc_b2 = (uc_b3 << 4) | uc_b4;
-                    uchar = (uc_b1 << 8) | uc_b2;
-
-                    if ((uchar & 0xF800) == 0xD800) {
-                        json_uchar uchar2;
-
-                        if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
-                            (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
-                            (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
-                            (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
-                            (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
-                        {
-                            sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
-                            goto e_failed;
-                        }
-
-                        uc_b1 = (uc_b1 << 4) | uc_b2;
-                        uc_b2 = (uc_b3 << 4) | uc_b4;
-                        uchar2 = (uc_b1 << 8) | uc_b2;
-
-                        uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
-                    }
-
-                    if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
-                    {
-                       string_add ((json_char) uchar);
-                       break;
-                    }
-
-                    if (uchar <= 0x7FF)
-                    {
-                        if (state.first_pass)
-                           string_length += 2;
-                        else
-                        {  string [string_length ++] = 0xC0 | (uchar >> 6);
-                           string [string_length ++] = 0x80 | (uchar & 0x3F);
-                        }
-
-                        break;
-                    }
-
-                    if (uchar <= 0xFFFF) {
-                        if (state.first_pass)
-                           string_length += 3;
-                        else
-                        {  string [string_length ++] = 0xE0 | (uchar >> 12);
-                           string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
-                           string [string_length ++] = 0x80 | (uchar & 0x3F);
-                        }
-
-                        break;
-                    }
-
-                    if (state.first_pass)
-                       string_length += 4;
-                    else
-                    {  string [string_length ++] = 0xF0 | (uchar >> 18);
-                       string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
-                       string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
-                       string [string_length ++] = 0x80 | (uchar & 0x3F);
-                    }
-
-                    break;
-
-                  default:
-                     string_add (b);
-               };
-
-               continue;
-            }
-
-            if (b == '\\')
-            {
-               flags |= flag_escaped;
-               continue;
-            }
-
-            if (b == '"')
-            {
-               if (!state.first_pass)
-                  string [string_length] = 0;
-
-               flags &= ~ flag_string;
-               string = 0;
-
-               switch (top->type)
-               {
-                  case json_string:
-
-                     top->u.string.length = string_length;
-                     flags |= flag_next;
-
-                     break;
-
-                  case json_object:
-
-                     if (state.first_pass)
-                        (*(json_char **) &top->u.object.values) += string_length + 1;
-                     else
-                     {
-                        top->u.object.values [top->u.object.length].name
-                           = (json_char *) top->_reserved.object_mem;
-
-                        top->u.object.values [top->u.object.length].name_length
-                           = string_length;
-
-                        (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
-                     }
-
-                     flags |= flag_seek_value | flag_need_colon;
-                     continue;
-
-                  default:
-                     break;
-               };
-            }
-            else
-            {
-               string_add (b);
-               continue;
-            }
-         }
-
-         if (state.settings.settings & json_enable_comments)
-         {
-            if (flags & (flag_line_comment | flag_block_comment))
-            {
-               if (flags & flag_line_comment)
-               {
-                  if (b == '\r' || b == '\n' || !b)
-                  {
-                     flags &= ~ flag_line_comment;
-                     -- state.ptr;  /* so null can be reproc'd */
-                  }
-
-                  continue;
-               }
-
-               if (flags & flag_block_comment)
-               {
-                  if (!b)
-                  {  sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
-                     goto e_failed;
-                  }
-
-                  if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
-                  {
-                     flags &= ~ flag_block_comment;
-                     ++ state.ptr;  /* skip closing sequence */
-                  }
-
-                  continue;
-               }
-            }
-            else if (b == '/')
-            {
-               if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
-               {  sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
-                  goto e_failed;
-               }
-
-               if (++ state.ptr == end)
-               {  sprintf (error, "%d:%d: EOF unexpected", line_and_col);
-                  goto e_failed;
-               }
-
-               switch (b = *state.ptr)
-               {
-                  case '/':
-                     flags |= flag_line_comment;
-                     continue;
-
-                  case '*':
-                     flags |= flag_block_comment;
-                     continue;
-
-                  default:
-                     sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
-                     goto e_failed;
-               };
-            }
-         }
-
-         if (flags & flag_done)
-         {
-            if (!b)
-               break;
-
-            switch (b)
-            {
-               whitespace:
-                  continue;
-
-               default:
-
-                  sprintf (error, "%d:%d: Trailing garbage: `%c`",
-                           state.cur_line, state.cur_col, b);
-
-                  goto e_failed;
-            };
-         }
-
-         if (flags & flag_seek_value)
-         {
-            switch (b)
-            {
-               whitespace:
-                  continue;
-
-               case ']':
-
-                  if (top && top->type == json_array)
-                     flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
-                  else
-                  {  sprintf (error, "%d:%d: Unexpected ]", line_and_col);
-                     goto e_failed;
-                  }
-
-                  break;
-
-               default:
-
-                  if (flags & flag_need_comma)
-                  {
-                     if (b == ',')
-                     {  flags &= ~ flag_need_comma;
-                        continue;
-                     }
-                     else
-                     {
-                        sprintf (error, "%d:%d: Expected , before %c",
-                                 state.cur_line, state.cur_col, b);
-
-                        goto e_failed;
-                     }
-                  }
-
-                  if (flags & flag_need_colon)
-                  {
-                     if (b == ':')
-                     {  flags &= ~ flag_need_colon;
-                        continue;
-                     }
-                     else
-                     {
-                        sprintf (error, "%d:%d: Expected : before %c",
-                                 state.cur_line, state.cur_col, b);
-
-                        goto e_failed;
-                     }
-                  }
-
-                  flags &= ~ flag_seek_value;
-
-                  switch (b)
-                  {
-                     case '{':
-
-                        if (!new_value (&state, &top, &root, &alloc, json_object))
-                           goto e_alloc_failure;
-
-                        continue;
-
-                     case '[':
-
-                        if (!new_value (&state, &top, &root, &alloc, json_array))
-                           goto e_alloc_failure;
-
-                        flags |= flag_seek_value;
-                        continue;
-
-                     case '"':
-
-                        if (!new_value (&state, &top, &root, &alloc, json_string))
-                           goto e_alloc_failure;
-
-                        flags |= flag_string;
-
-                        string = top->u.string.ptr;
-                        string_length = 0;
-
-                        continue;
-
-                     case 't':
-
-                        if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
-                            *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
-                        {
-                           goto e_unknown_value;
-                        }
-
-                        if (!new_value (&state, &top, &root, &alloc, json_boolean))
-                           goto e_alloc_failure;
-
-                        top->u.boolean = 1;
-
-                        flags |= flag_next;
-                        break;
-
-                     case 'f':
-
-                        if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
-                            *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
-                            *(++ state.ptr) != 'e')
-                        {
-                           goto e_unknown_value;
-                        }
-
-                        if (!new_value (&state, &top, &root, &alloc, json_boolean))
-                           goto e_alloc_failure;
-
-                        flags |= flag_next;
-                        break;
-
-                     case 'n':
-
-                        if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
-                            *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
-                        {
-                           goto e_unknown_value;
-                        }
-
-                        if (!new_value (&state, &top, &root, &alloc, json_null))
-                           goto e_alloc_failure;
-
-                        flags |= flag_next;
-                        break;
-
-                     default:
-
-                        if (isdigit (b) || b == '-')
-                        {
-                           if (!new_value (&state, &top, &root, &alloc, json_integer))
-                              goto e_alloc_failure;
-
-                           if (!state.first_pass)
-                           {
-                              while (isdigit (b) || b == '+' || b == '-'
-                                        || b == 'e' || b == 'E' || b == '.')
-                              {
-                                 if ( (++ state.ptr) == end)
-                                 {
-                                    b = 0;
-                                    break;
-                                 }
-
-                                 b = *state.ptr;
-                              }
-
-                              flags |= flag_next | flag_reproc;
-                              break;
-                           }
-
-                           flags &= ~ (flag_num_negative | flag_num_e |
-                                        flag_num_e_got_sign | flag_num_e_negative |
-                                           flag_num_zero);
-
-                           num_digits = 0;
-                           num_fraction = 0;
-                           num_e = 0;
-
-                           if (b != '-')
-                           {
-                              flags |= flag_reproc;
-                              break;
-                           }
-
-                           flags |= flag_num_negative;
-                           continue;
-                        }
-                        else
-                        {  sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
-                           goto e_failed;
-                        }
-                  };
-            };
-         }
-         else
-         {
-            switch (top->type)
-            {
-            case json_object:
-
-               switch (b)
-               {
-                  whitespace:
-                     continue;
-
-                  case '"':
-
-                     if (flags & flag_need_comma)
-                     {  sprintf (error, "%d:%d: Expected , before \"", line_and_col);
-                        goto e_failed;
-                     }
-
-                     flags |= flag_string;
-
-                     string = (json_char *) top->_reserved.object_mem;
-                     string_length = 0;
-
-                     break;
-
-                  case '}':
-
-                     flags = (flags & ~ flag_need_comma) | flag_next;
-                     break;
-
-                  case ',':
-
-                     if (flags & flag_need_comma)
-                     {
-                        flags &= ~ flag_need_comma;
-                        break;
-                     }
-
-                  default:
-                     sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
-                     goto e_failed;
-               };
-
-               break;
-
-            case json_integer:
-            case json_double:
-
-               if (isdigit (b))
-               {
-                  ++ num_digits;
-
-                  if (top->type == json_integer || flags & flag_num_e)
-                  {
-                     if (! (flags & flag_num_e))
-                     {
-                        if (flags & flag_num_zero)
-                        {  sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
-                           goto e_failed;
-                        }
-
-                        if (num_digits == 1 && b == '0')
-                           flags |= flag_num_zero;
-                     }
-                     else
-                     {
-                        flags |= flag_num_e_got_sign;
-                        num_e = (num_e * 10) + (b - '0');
-                        continue;
-                     }
-
-                     top->u.integer = (top->u.integer * 10) + (b - '0');
-                     continue;
-                  }
-
-                  num_fraction = (num_fraction * 10) + (b - '0');
-                  continue;
-               }
-
-               if (b == '+' || b == '-')
-               {
-                  if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
-                  {
-                     flags |= flag_num_e_got_sign;
-
-                     if (b == '-')
-                        flags |= flag_num_e_negative;
-
-                     continue;
-                  }
-               }
-               else if (b == '.' && top->type == json_integer)
-               {
-                  if (!num_digits)
-                  {  sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
-                     goto e_failed;
-                  }
-
-                  top->type = json_double;
-                  top->u.dbl = (double) top->u.integer;
-
-                  num_digits = 0;
-                  continue;
-               }
-
-               if (! (flags & flag_num_e))
-               {
-                  if (top->type == json_double)
-                  {
-                     if (!num_digits)
-                     {  sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
-                        goto e_failed;
-                     }
-
-                     top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));
-                  }
-
-                  if (b == 'e' || b == 'E')
-                  {
-                     flags |= flag_num_e;
-
-                     if (top->type == json_integer)
-                     {
-                        top->type = json_double;
-                        top->u.dbl = (double) top->u.integer;
-                     }
-
-                     num_digits = 0;
-                     flags &= ~ flag_num_zero;
-
-                     continue;
-                  }
-               }
-               else
-               {
-                  if (!num_digits)
-                  {  sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
-                     goto e_failed;
-                  }
-
-                  top->u.dbl *= pow (10.0, (double)
-                      (flags & flag_num_e_negative ? - num_e : num_e));
-               }
-
-               if (flags & flag_num_negative)
-               {
-                  if (top->type == json_integer)
-                     top->u.integer = - top->u.integer;
-                  else
-                     top->u.dbl = - top->u.dbl;
-               }
-
-               flags |= flag_next | flag_reproc;
-               break;
-
-            default:
-               break;
-            };
-         }
-
-         if (flags & flag_reproc)
-         {
-            flags &= ~ flag_reproc;
-            -- state.ptr;
-         }
-
-         if (flags & flag_next)
-         {
-            flags = (flags & ~ flag_next) | flag_need_comma;
-
-            if (!top->parent)
-            {
-               /* root value done */
-
-               flags |= flag_done;
-               continue;
-            }
-
-            if (top->parent->type == json_array)
-               flags |= flag_seek_value;
-
-            if (!state.first_pass)
-            {
-               json_value * parent = top->parent;
-
-               switch (parent->type)
-               {
-                  case json_object:
-
-                     parent->u.object.values
-                        [parent->u.object.length].value = top;
-
-                     break;
-
-                  case json_array:
-
-                     parent->u.array.values
-                           [parent->u.array.length] = top;
-
-                     break;
-
-                  default:
-                     break;
-               };
-            }
-
-            if ( (++ top->parent->u.array.length) > state.uint_max)
-               goto e_overflow;
-
-            top = top->parent;
-
-            continue;
-         }
-      }
-
-      alloc = root;
-   }
-
-   return root;
-
-e_unknown_value:
-
-   sprintf (error, "%d:%d: Unknown value", line_and_col);
-   goto e_failed;
-
-e_alloc_failure:
-
-   strcpy (error, "Memory allocation failure");
-   goto e_failed;
-
-e_overflow:
-
-   sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
-   goto e_failed;
-
-e_failed:
-
-   if (error_buf)
-   {
-      if (*error)
-         strcpy (error_buf, error);
-      else
-         strcpy (error_buf, "Unknown error");
-   }
-
-   if (state.first_pass)
-      alloc = root;
-
-   while (alloc)
-   {
-      top = alloc->_reserved.next_alloc;
-      state.settings.mem_free (alloc, state.settings.user_data);
-      alloc = top;
-   }
-
-   if (!state.first_pass)
-      json_value_free_ex (&state.settings, root);
-
-   return 0;
-}
-
-json_value * json_parse (const json_char * json, size_t length)
-{
-   json_settings settings = { 0 };
-   return json_parse_ex (&settings, json, length, 0);
-}
-
-void json_value_free_ex (json_settings * settings, json_value * value)
-{
-   json_value * cur_value;
-
-   if (!value)
-      return;
-
-   value->parent = 0;
-
-   while (value)
-   {
-      switch (value->type)
-      {
-         case json_array:
-
-            if (!value->u.array.length)
-            {
-               settings->mem_free (value->u.array.values, settings->user_data);
-               break;
-            }
-
-            value = value->u.array.values [-- value->u.array.length];
-            continue;
-
-         case json_object:
-
-            if (!value->u.object.length)
-            {
-               settings->mem_free (value->u.object.values, settings->user_data);
-               break;
-            }
-
-            value = value->u.object.values [-- value->u.object.length].value;
-            continue;
-
-         case json_string:
-
-            settings->mem_free (value->u.string.ptr, settings->user_data);
-            break;
-
-         default:
-            break;
-      };
-
-      cur_value = value;
-      value = value->parent;
-      settings->mem_free (cur_value, settings->user_data);
-   }
-}
-
-void json_value_free (json_value * value)
-{
-   json_settings settings = { 0 };
-   settings.mem_free = default_free;
-   json_value_free_ex (&settings, value);
-}
-


=====================================
modules/misc/webservices/json.h deleted
=====================================
@@ -1,278 +0,0 @@
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
- *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved.
- * https://github.com/udp/json-parser
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef VLC_WEBSERVICES_JSON_H_
-#define VLC_WEBSERVICES_JSON_H_
-
-#ifndef json_char
-   #define json_char char
-#endif
-
-#ifndef json_int_t
-   #ifndef _MSC_VER
-      #include <inttypes.h>
-      #define json_int_t int64_t
-   #else
-      #define json_int_t __int64
-   #endif
-#endif
-
-#include <stdlib.h>
-
-#ifdef __cplusplus
-
-   #include <string.h>
-
-   extern "C"
-   {
-
-#endif
-
-typedef struct
-{
-   unsigned long max_memory;
-   int settings;
-
-   /* Custom allocator support (leave null to use malloc/free)
-    */
-
-   void * (* mem_alloc) (size_t, int zero, void * user_data);
-   void (* mem_free) (void *, void * user_data);
-
-   void * user_data;  /* will be passed to mem_alloc and mem_free */
-
-   size_t value_extra;  /* how much extra space to allocate for values? */
-
-} json_settings;
-
-#define json_enable_comments  0x01
-
-typedef enum
-{
-   json_none,
-   json_object,
-   json_array,
-   json_integer,
-   json_double,
-   json_string,
-   json_boolean,
-   json_null
-
-} json_type;
-
-extern const struct _json_value json_value_none;
-
-typedef struct _json_value
-{
-   struct _json_value * parent;
-
-   json_type type;
-
-   union
-   {
-      int boolean;
-      json_int_t integer;
-      double dbl;
-
-      struct
-      {
-         unsigned int length;
-         json_char * ptr; /* null terminated */
-
-      } string;
-
-      struct
-      {
-         unsigned int length;
-
-         struct
-         {
-            json_char * name;
-            unsigned int name_length;
-
-            struct _json_value * value;
-
-         } * values;
-
-         #if defined(__cplusplus) && __cplusplus >= 201103L
-         decltype(values) begin () const
-         {  return values;
-         }
-         decltype(values) end () const
-         {  return values + length;
-         }
-         #endif
-
-      } object;
-
-      struct
-      {
-         unsigned int length;
-         struct _json_value ** values;
-
-         #if defined(__cplusplus) && __cplusplus >= 201103L
-         decltype(values) begin () const
-         {  return values;
-         }
-         decltype(values) end () const
-         {  return values + length;
-         }
-         #endif
-
-      } array;
-
-   } u;
-
-   union
-   {
-      struct _json_value * next_alloc;
-      void * object_mem;
-
-   } _reserved;
-
-   #ifdef JSON_TRACK_SOURCE
-
-      /* Location of the value in the source JSON
-       */
-      unsigned int line, col;
-
-   #endif
-
-
-   /* Some C++ operator sugar */
-
-   #ifdef __cplusplus
-
-      public:
-
-         inline _json_value ()
-         {  memset (this, 0, sizeof (_json_value));
-         }
-
-         inline const struct _json_value &operator [] (int index) const
-         {
-            if (type != json_array || index < 0
-                     || ((unsigned int) index) >= u.array.length)
-            {
-               return json_value_none;
-            }
-
-            return *u.array.values [index];
-         }
-
-         inline const struct _json_value &operator [] (const char * index) const
-         {
-            if (type != json_object)
-               return json_value_none;
-
-            for (unsigned int i = 0; i < u.object.length; ++ i)
-               if (!strcmp (u.object.values [i].name, index))
-                  return *u.object.values [i].value;
-
-            return json_value_none;
-         }
-
-         inline operator const char * () const
-         {
-            switch (type)
-            {
-               case json_string:
-                  return u.string.ptr;
-
-               default:
-                  return "";
-            };
-         }
-
-         inline operator json_int_t () const
-         {
-            switch (type)
-            {
-               case json_integer:
-                  return u.integer;
-
-               case json_double:
-                  return (json_int_t) u.dbl;
-
-               default:
-                  return 0;
-            };
-         }
-
-         inline operator bool () const
-         {
-            if (type != json_boolean)
-               return false;
-
-            return u.boolean != 0;
-         }
-
-         inline operator double () const
-         {
-            switch (type)
-            {
-               case json_integer:
-                  return (double) u.integer;
-
-               case json_double:
-                  return u.dbl;
-
-               default:
-                  return 0;
-            };
-         }
-
-   #endif
-
-} json_value;
-
-json_value * json_parse (const json_char * json,
-                         size_t length);
-
-#define json_error_max 128
-json_value * json_parse_ex (json_settings * settings,
-                            const json_char * json,
-                            size_t length,
-                            char * error);
-
-void json_value_free (json_value *);
-
-
-/* Not usually necessary, unless you used a custom mem_alloc and now want to
- * use a custom mem_free.
- */
-void json_value_free_ex (json_settings * settings,
-                         json_value *);
-
-
-#ifdef __cplusplus
-   } /* extern "C" */
-#endif
-
-#endif


=====================================
modules/misc/webservices/json_helper.h
=====================================
@@ -26,59 +26,15 @@
 
 #include <limits.h>
 
-#include "json.h"
+#include "../../demux/json/json.h"
 
 static inline
-const json_value * json_getbyname(const json_value *object, const char *psz_name)
+char * json_dupstring(const struct json_object *obj, const char *key)
 {
-    if (object->type != json_object) return NULL;
-    for (unsigned int i=0; i < object->u.object.length; i++)
-        if (strcmp(object->u.object.values[i].name, psz_name) == 0)
-            return object->u.object.values[i].value;
-    return NULL;
-}
-
-static inline
-char * jsongetstring(const json_value *node, const char *key)
-{
-    node = json_getbyname(node, key);
-    if (node && node->type == json_string)
-        return node->u.string.ptr;
-    return NULL;
-}
-
-static inline
-char * json_dupstring(const json_value *node, const char *key)
-{
-    const char *str = jsongetstring(node, key);
+    const char *str = json_get_str(obj, key);
     return (str) ? strdup(str) : NULL;
 }
 
-static inline
-json_value * json_parse_document(vlc_object_t *p_obj, const char *psz_buffer, size_t i_buffer)
-{
-    json_settings settings;
-    char psz_error[128];
-    memset (&settings, 0, sizeof (json_settings));
-    json_value *root = json_parse_ex(&settings, psz_buffer, i_buffer, psz_error);
-    if (root == NULL)
-    {
-        msg_Warn(p_obj, "Can't parse json data: %s", psz_error);
-        goto error;
-    }
-    if (root->type != json_object)
-    {
-        msg_Warn(p_obj, "wrong json root node");
-        goto error;
-    }
-
-    return root;
-
-error:
-    if (root) json_value_free(root);
-    return NULL;
-}
-
 static inline
 void * json_retrieve_document(vlc_object_t *p_obj, const char *psz_url, size_t *buf_size)
 {
@@ -123,4 +79,30 @@ void * json_retrieve_document(vlc_object_t *p_obj, const char *psz_url, size_t *
     return p_buffer;
 }
 
+struct json_helper_sys {
+    struct vlc_logger *logger;
+    const char *buffer;
+    size_t size;
+};
+
+void json_parse_error(void *data, const char *msg)
+{
+    struct json_helper_sys *sys = data;
+
+    vlc_error(sys->logger, "%s", msg);
+}
+
+size_t json_read(void *data, void *buf, size_t size)
+{
+    struct json_helper_sys *sys = data;
+
+    /* Read the smallest number of byte between size and the string length */
+    size_t s = size < sys->size ? size : sys->size; 
+    memcpy(buf, sys->buffer, s);
+
+    sys->buffer += s;
+    sys->size -= s;
+    return s;
+}
+
 #endif


=====================================
modules/misc/webservices/musicbrainz.c
=====================================
@@ -24,18 +24,20 @@
 #include <string.h>
 #include <limits.h>
 
+#include <vlc_common.h>
+#include <vlc_messages.h>
+
 #include "json_helper.h"
 #include "musicbrainz.h"
 
 typedef struct
 {
-    json_value *root;
+    struct json_object json;
 } musicbrainz_lookup_t;
 
 static void musicbrainz_lookup_release(musicbrainz_lookup_t *p)
 {
-    if(p && p->root)
-        json_value_free(p->root);
+    json_free(&p->json);
     free(p);
 }
 
@@ -53,86 +55,98 @@ static musicbrainz_lookup_t * musicbrainz_lookup(vlc_object_t *p_obj, const char
         return NULL;
 
     musicbrainz_lookup_t *p_lookup = musicbrainz_lookup_new();
+
     if(p_lookup)
     {
-        p_lookup->root = json_parse_document(p_obj, p_buffer, i_buffer);
-        if (!p_lookup->root)
-            msg_Dbg(p_obj, "No results");
+        struct json_helper_sys sys;
+        sys.logger = p_obj->logger;
+        sys.buffer = p_buffer;
+        sys.size = i_buffer;
+
+        int val = json_parse(&sys, &p_lookup->json);        
+        if (val) {
+            msg_Dbg( p_obj, "error: could not parse json!");
+            free(p_buffer);
+            return false;
+        }
     }
     free(p_buffer);
     return p_lookup;
 }
 
-static bool musicbrainz_fill_track(const json_value *tracknode, musicbrainz_track_t *t)
+static bool musicbrainz_fill_track(const struct json_object *trackobj, musicbrainz_track_t *t)
 {
-    t->psz_title = json_dupstring(tracknode, "title");
+    t->psz_title = json_dupstring(trackobj, "title");
 
-    const json_value *node = json_getbyname(tracknode, "artist-credit");
-    if (node && node->type == json_array && node->u.array.length)
-        t->psz_artist = json_dupstring(node->u.array.values[0], "name");
+    const struct json_array *array = json_get_array(trackobj, "artist-credit");
+    if (array != NULL && array->size >= 1) {
+        const struct json_value *artist = &array->entries[0];
+        if (artist->type == JSON_OBJECT)
+            t->psz_artist = json_dupstring(&artist->object, "name");
+    }
 
-    node = json_getbyname(tracknode, "position");
-    if (node && node->type == json_integer)
-        t->i_index = node->u.integer;
+    double pos = json_get_num(trackobj, "position");
+    if (pos != NAN) {
+        t->i_index = pos;
+    }
 
     return true;
 }
 
-static bool musicbrainz_has_cover_in_releasegroup(json_value ** const p_nodes,
+static bool musicbrainz_has_cover_in_releasegroup(const struct json_value *p_nodes,
                                                   size_t i_nodes,
                                                   const char *psz_group_id)
 {
+    /* FIXME, not sure it does what I want */
     for(size_t i=0; i<i_nodes; i++)
     {
-        const json_value *rgnode = json_getbyname(p_nodes[i], "release-group");
-        if(rgnode)
-        {
-            const char *psz_id = jsongetstring(rgnode, "id");
-            if(!psz_id || strcmp(psz_id, psz_group_id))
-                continue;
-
-            const json_value *node = json_getbyname(p_nodes[i], "cover-art-archive");
-            if(!node)
-                continue;
+        if (p_nodes[i].type != JSON_OBJECT)
+            continue;
+        const struct json_object *obj = &p_nodes[i].object;
 
-            node = json_getbyname(node, "front");
-            if(!node || node->type != json_boolean || !node->u.boolean)
-                continue;
+        const struct json_object *rgobj = json_get_object(obj, "release-group");
+        if (rgobj == NULL)
+            continue;
+        const char *psz_id = json_get_str(rgobj, "id");
+        if(!psz_id || strcmp(psz_id, psz_group_id))
+            continue;
+        
+        const struct json_object *cover = json_get_object(obj, "cover-art-archive");
+        if (cover == NULL)
+            continue;
+        const struct json_value *node = json_get(cover, "front");
+        if (node == NULL)
+            continue;
+        if(node->type != JSON_BOOLEAN || !node->boolean)
+            continue;
 
-            return true;
-        }
+        return true;
     }
 
     return false;
 }
 
-static char *musicbrainz_fill_artists(const json_value *arraynode)
+static char *musicbrainz_fill_artists(const struct json_array *array)
 {
     char *psz = NULL;
-    if(arraynode->type != json_array || arraynode->u.array.length < 1)
-        return psz;
 
-    size_t i_total = 1;
-    for(size_t i=0; i<arraynode->u.array.length; i++)
+    for(size_t i = 0; i < array->size; i++)
     {
-        const json_value *name = json_getbyname(arraynode->u.array.values[i], "name");
-        if(name->type != json_string)
+        if (array->entries[i].type != JSON_OBJECT)
             continue;
+        const struct json_object *obj = &array->entries[i].object;
 
-        if(psz == NULL)
-        {
-            psz = strdup(name->u.string.ptr);
-            i_total = name->u.string.length + 1;
+        const char *name = json_get_str(obj, "name");
+        if (name == NULL)
+            continue;
+        if(psz == NULL) {
+            psz = strdup(name);
         }
-        else
-        {
-            char *p = realloc(psz, i_total + name->u.string.length + 2);
-            if(p)
-            {
+        else {
+            char *p = NULL;
+            if (asprintf(&p, "%s, %s", psz, name) > 0) {
+                free(psz);
                 psz = p;
-                psz = strcat(psz, ", ");
-                psz = strncat(psz, name->u.string.ptr, name->u.string.length);
-                i_total += name->u.string.length + 2;
             }
         }
     }
@@ -140,55 +154,54 @@ static char *musicbrainz_fill_artists(const json_value *arraynode)
     return psz;
 }
 
-static bool musicbrainz_fill_release(const json_value *releasenode, musicbrainz_release_t *r)
+static bool musicbrainz_fill_release(const struct json_object *release,
+                                     musicbrainz_release_t *r)
 {
-    const json_value *media = json_getbyname(releasenode, "media");
-    if(!media || media->type != json_array ||
-       media->u.array.length == 0)
+    const struct json_array *media_array = json_get_array(release, "media");
+    if (media_array == NULL && media_array->size == 0)
         return false;
     /* we always use first media */
-    media = media->u.array.values[0];
+    const struct json_value *media = &media_array->entries[0];
+    if (media->type != JSON_OBJECT)
+        return false;
 
-    const json_value *tracks = json_getbyname(media, "tracks");
-    if(!tracks || tracks->type != json_array ||
-       tracks->u.array.length == 0)
+    const struct json_array *tracks = json_get_array(&media->object, "tracks");
+    if (tracks == NULL && tracks->size == 0)
         return false;
 
-    r->p_tracks = calloc(tracks->u.array.length, sizeof(*r->p_tracks));
+    r->p_tracks = calloc(tracks->size, sizeof(*r->p_tracks));
     if(!r->p_tracks)
         return false;
 
-    for(size_t i=0; i<tracks->u.array.length; i++)
+    for(size_t i = 0; i < tracks->size; i++)
     {
-        if(musicbrainz_fill_track(tracks->u.array.values[i], &r->p_tracks[r->i_tracks]))
+        if (tracks->entries[i].type != JSON_OBJECT)
+            continue;
+        const struct json_object *trackobj = &tracks->entries[i].object;
+        if(musicbrainz_fill_track(trackobj, &r->p_tracks[r->i_tracks]))
             r->i_tracks++;
     }
 
-    r->psz_title = json_dupstring(releasenode, "title");
-    r->psz_id = json_dupstring(releasenode, "id");
+    r->psz_title = json_dupstring(release, "title");
+    r->psz_id = json_dupstring(release, "id");
 
-    const json_value *rgnode = json_getbyname(releasenode, "release-group");
-    if(rgnode)
-    {
-        r->psz_date = json_dupstring(rgnode, "first-release-date");
-        r->psz_group_id = json_dupstring(rgnode, "id");
+    const struct json_object *rg = json_get_object(release,
+                                                   "release-group");
+    if (rg != NULL) {
+        r->psz_date = json_dupstring(rg, "first-release-date");
+        r->psz_group_id = json_dupstring(rg, "id");
 
-        const json_value *node = json_getbyname(rgnode, "artist-credit");
-        if(node)
-            r->psz_artist = musicbrainz_fill_artists(node);
+        const struct json_array *artists = json_get_array(rg, "artist-credit");
+        if (artists != NULL)
+            r->psz_artist = musicbrainz_fill_artists(artists);
     }
-    else
-    {
-        const json_value *node = json_getbyname(releasenode, "artist-credit");
-        if(node)
-            r->psz_artist = musicbrainz_fill_artists(node);
-
-        node = json_getbyname(releasenode, "release-events");
-        if(node && node->type == json_array && node->u.array.length)
-            r->psz_date = json_dupstring(node->u.array.values[0], "date");
+    const struct json_array *events = json_get_array(release,
+                                                     "release-events");
+    if (events != NULL && events->size > 0) {
+        if (events->entries[0].type == JSON_OBJECT)
+            r->psz_date = json_dupstring(&events->entries[0].object, "date");
     }
 
-
     return true;
 }
 
@@ -227,25 +240,24 @@ static musicbrainz_recording_t *musicbrainz_lookup_recording_by_apiurl(vlc_objec
         return NULL;
     }
 
-    const json_value *releases = json_getbyname(lookup->root, "releases");
-    if (releases && releases->type == json_array &&
-        releases->u.array.length)
+    const struct json_array *releases = json_get_array(&lookup->json, "releases");
+    if (releases != NULL && releases->size)
     {
-        r->p_releases = calloc(releases->u.array.length, sizeof(*r->p_releases));
+        r->p_releases = calloc(releases->size, sizeof(*r->p_releases));
         if(r->p_releases)
         {
-            for(unsigned i=0; i<releases->u.array.length; i++)
+            for(unsigned i = 0; i < releases->size; i++)
             {
-                json_value *node = releases->u.array.values[i];
                 musicbrainz_release_t *p_mbrel = &r->p_releases[r->i_release];
-                if (!node || node->type != json_object ||
-                    !musicbrainz_fill_release(node, p_mbrel))
+                const struct json_value *node = &releases->entries[i];
+                if (node->type != JSON_OBJECT ||
+                    !musicbrainz_fill_release(&node->object, p_mbrel))
                     continue;
 
                 /* Try to find cover from other releases from the same group */
                 if(p_mbrel->psz_group_id && !p_mbrel->psz_coverart_url &&
-                   musicbrainz_has_cover_in_releasegroup(releases->u.array.values,
-                                                         releases->u.array.length,
+                   musicbrainz_has_cover_in_releasegroup(releases->entries,
+                                                         releases->size,
                                                          p_mbrel->psz_group_id))
                 {
                     char *psz_art = coverartarchive_make_releasegroup_arturl(
@@ -349,3 +361,4 @@ coverartarchive_t * coverartarchive_lookup_releasegroup(musicbrainz_config_t *cf
 
     return c;
 }
+


=====================================
modules/stream_out/Makefile.am
=====================================
@@ -140,10 +140,10 @@ libstream_out_chromecast_plugin_la_SOURCES = stream_out/chromecast/cast.cpp stre
                                              stream_out/renderer_common.hpp \
                                              stream_out/renderer_common.cpp \
                                              stream_out/chromecast/chromecast_common.h stream_out/chromecast/chromecast_ctrl.cpp \
-                                             misc/webservices/json.h misc/webservices/json.c stream_out/chromecast/chromecast_communication.cpp
+                                             stream_out/chromecast/chromecast_communication.cpp
 nodist_libstream_out_chromecast_plugin_la_SOURCES = stream_out/chromecast/@PROTOBUF_VERSION@/cast_channel.pb.cc
 libstream_out_chromecast_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -Istream_out/chromecast/@PROTOBUF_VERSION@ $(CHROMECAST_CFLAGS)
-libstream_out_chromecast_plugin_la_LIBADD = $(CHROMECAST_LIBS) $(SOCKET_LIBS)
+libstream_out_chromecast_plugin_la_LIBADD = $(CHROMECAST_LIBS) $(SOCKET_LIBS) libvlc_json.la 
 CLEANFILES += $(nodist_libstream_out_chromecast_plugin_la_SOURCES)
 
 if ENABLE_SOUT


=====================================
modules/stream_out/chromecast/chromecast.h
=====================================
@@ -221,10 +221,10 @@ private:
 
     void mainLoop();
     void processAuthMessage( const castchannel::CastMessage& msg );
-    void processHeartBeatMessage( const castchannel::CastMessage& msg );
-    bool processReceiverMessage( const castchannel::CastMessage& msg );
-    void processMediaMessage( const castchannel::CastMessage& msg );
-    void processConnectionMessage( const castchannel::CastMessage& msg );
+    void processHeartBeatMessage( const castchannel::CastMessage& msg , const struct json_object *entry );
+    bool processReceiverMessage( const castchannel::CastMessage& msg , const struct json_object *entry );
+    void processMediaMessage( const castchannel::CastMessage& msg , const struct json_object *entry );
+    void processConnectionMessage( const castchannel::CastMessage& msg , const struct json_object *entry );
 
 private:
     static void* ChromecastThread(void* p_data);


=====================================
modules/stream_out/chromecast/chromecast_ctrl.cpp
=====================================
@@ -41,12 +41,47 @@
 #include <vlc_rand.h>
 #include <vlc_threads.h>
 
-#include "../../misc/webservices/json.h"
+extern "C" {
+#include "../../demux/json/json.h"
+}
 
 /* deadline regarding pings sent from receiver */
 #define PING_WAIT_TIME 6000
 #define PING_WAIT_RETRIES 1
 
+extern "C" {
+
+struct chromecast_ctrl_json {
+    struct vlc_logger *logger;
+    const char *string;
+};
+
+void json_parse_error(void *data, const char *msg)
+{
+    vlc_assert(data != NULL);
+
+    struct chromecast_ctrl_json *sys = static_cast<struct chromecast_ctrl_json *>(data);
+    vlc_error(sys->logger, "%s", msg);
+}
+
+size_t json_read(void *data, void *buf, size_t size)
+{
+    vlc_assert(data != NULL);
+    vlc_assert(buf != NULL);
+
+    struct chromecast_ctrl_json *sys = static_cast<struct chromecast_ctrl_json *>(data);
+    size_t len = strlen(sys->string);
+
+    /* Read the smallest number of byte between size and the string length */
+    size_t s = size < len ? size : len; 
+    memcpy(buf, sys->string, s);
+
+    sys->string += s;
+    return s;
+}
+
+}
+
 static int httpd_file_fill_cb( httpd_file_sys_t *data, httpd_file_t *http_file,
                           uint8_t *psz_request, uint8_t **pp_data, size_t *pi_data );
 
@@ -538,6 +573,7 @@ void intf_sys_t::sendInputEvent(enum cc_input_event event, union cc_input_arg ar
  * @param msg the CastMessage to process
  * @return 0 if the message has been successfully processed else -1
  */
+
 bool intf_sys_t::processMessage(const castchannel::CastMessage &msg)
 {
     const std::string & namespace_ = msg.namespace_();
@@ -546,21 +582,40 @@ bool intf_sys_t::processMessage(const castchannel::CastMessage &msg)
     msg_Dbg( m_module, "processMessage: %s->%s %s", namespace_.c_str(), msg.destination_id().c_str(), msg.payload_utf8().c_str());
 #endif
 
-    bool ret = true;
-    if (namespace_ == NAMESPACE_DEVICEAUTH)
+    if (namespace_ == NAMESPACE_DEVICEAUTH) {
         processAuthMessage( msg );
-    else if (namespace_ == NAMESPACE_HEARTBEAT)
-        processHeartBeatMessage( msg );
+        return true;
+    }
+    if ((namespace_ != NAMESPACE_HEARTBEAT)
+        && (namespace_ != NAMESPACE_RECEIVER)
+        && (namespace_ != NAMESPACE_MEDIA)
+        && (namespace_ != NAMESPACE_CONNECTION)) {
+        msg_Err( m_module, "Unknown namespace: %s", namespace_.c_str());
+        return false;
+    }
+
+    struct chromecast_ctrl_json sys;
+    sys.logger = m_module->logger;
+    sys.string = msg.payload_utf8().c_str();
+
+    struct json_object json;
+    int val = json_parse(&sys, &json);
+    if (val) {
+        msg_Dbg(m_module, "error: could not parse json!");
+        return false;
+    }
+
+    bool ret = true;
+    if (namespace_ == NAMESPACE_HEARTBEAT)
+        processHeartBeatMessage(msg , &json);
     else if (namespace_ == NAMESPACE_RECEIVER)
-        ret = processReceiverMessage( msg );
+        ret = processReceiverMessage(msg , &json);
     else if (namespace_ == NAMESPACE_MEDIA)
-        processMediaMessage( msg );
+        processMediaMessage(msg , &json);
     else if (namespace_ == NAMESPACE_CONNECTION)
-        processConnectionMessage( msg );
-    else
-    {
-        msg_Err( m_module, "Unknown namespace: %s", msg.namespace_().c_str());
-    }
+        processConnectionMessage(msg , &json);
+
+    json_free(&json);
     return ret;
 }
 
@@ -667,11 +722,11 @@ void intf_sys_t::processAuthMessage( const castchannel::CastMessage& msg )
     }
 }
 
-void intf_sys_t::processHeartBeatMessage( const castchannel::CastMessage& msg )
+void intf_sys_t::processHeartBeatMessage( const castchannel::CastMessage& msg , const struct json_object *entry )
 {
-    json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length());
-    std::string type((*p_data)["type"]);
-
+    VLC_UNUSED(msg);
+    const char *tmp = json_get_str(entry, "type");
+    std::string type = tmp ? tmp : ""; 
     if (type == "PING")
     {
         msg_Dbg( m_module, "PING received from the Chromecast");
@@ -686,33 +741,38 @@ void intf_sys_t::processHeartBeatMessage( const castchannel::CastMessage& msg )
     {
         msg_Warn( m_module, "Heartbeat command not supported: %s", type.c_str());
     }
-
-    json_value_free(p_data);
 }
 
-bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
+bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg , const struct json_object *entry )
 {
-    json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length());
-    std::string type((*p_data)["type"]);
+    const char *tmp = json_get_str(entry, "type");
+    std::string type = tmp ? tmp : "";
 
     bool ret = true;
     if (type == "RECEIVER_STATUS")
     {
-        json_value applications = (*p_data)["status"]["applications"];
-        const json_value *p_app = NULL;
-
-        for (unsigned i = 0; i < applications.u.array.length; ++i)
-        {
-            if ( strcmp( applications[i]["appId"], APP_ID ) == 0 )
+        const json_value *status = json_get(entry, "status");
+        if (!status) {
+            msg_Err(m_module, "receiver message: bad payload");
+            return false;
+        }
+        const json_value *applications = json_get(&status->object, "applications");
+        const json_object *p_app = NULL;
+        if (applications) {
+            for (unsigned i = 0; i < applications->array.size; ++i)
             {
-                if ( (const char*)applications[i]["transportId"] != NULL)
+                const char *appId = json_get_str(&applications->array.entries[i].object, "appId");
+                const char *transportId = json_get_str(&applications->array.entries[i].object, "transportId");
+                if ( strcmp( appId, APP_ID ) == 0 ) 
                 {
-                    p_app = &applications[i];
-                    break;
+                    if (  transportId != NULL )
+                    {
+                        p_app = &applications->array.entries[i].object;
+                        break;
+                    }
                 }
             }
         }
-
         vlc::threads::mutex_locker lock( m_lock );
 
         switch ( m_state )
@@ -723,7 +783,8 @@ bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
             if ( p_app != NULL )
             {
                 msg_Dbg( m_module, "Media receiver application was already running" );
-                m_appTransportId = (const char*)(*p_app)["transportId"];
+                tmp = json_get_str(p_app, "transportId");
+                m_appTransportId = tmp ? tmp: "";
                 m_communication->msgConnect( m_appTransportId );
                 setState( Ready );
             }
@@ -737,7 +798,8 @@ bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
             if ( p_app != NULL )
             {
                 msg_Dbg( m_module, "Media receiver application has been started." );
-                m_appTransportId = (const char*)(*p_app)["transportId"];
+                tmp = json_get_str(p_app, "transportId");
+                m_appTransportId = tmp ? tmp: "";
                 m_communication->msgConnect( m_appTransportId );
                 setState( Ready );
             }
@@ -775,9 +837,9 @@ bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
     }
     else if (type == "LAUNCH_ERROR")
     {
-        json_value reason = (*p_data)["reason"];
+        const char *reason = json_get_str(entry, "reason");
         msg_Err( m_module, "Failed to start the MediaPlayer: %s",
-                (const char *)reason);
+                 reason);
         vlc::threads::mutex_locker lock( m_lock );
         m_appTransportId = "";
         m_mediaSessionId = 0;
@@ -790,41 +852,44 @@ bool intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
                 msg.payload_utf8().c_str());
     }
 
-    json_value_free(p_data);
     return ret;
 }
 
-void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
+void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg , const struct json_object *entry )
 {
-    json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length());
-    std::string type((*p_data)["type"]);
-    int64_t requestId = (json_int_t) (*p_data)["requestId"];
+    const char *tmp = json_get_str(entry, "type");
+    std::string type = tmp ? tmp: "";
+    int64_t requestId = (int64_t) json_get_num(entry,"requestId");
 
     vlc::threads::mutex_locker lock( m_lock );
 
     if ((m_last_request_id != 0 && requestId != m_last_request_id))
-    {
-        json_value_free(p_data);
         return;
-    }
     m_last_request_id = 0;
 
     if (type == "MEDIA_STATUS")
     {
-        json_value status = (*p_data)["status"];
-
-        int64_t sessionId = (json_int_t) status[0]["mediaSessionId"];
-        std::string newPlayerState = (const char*)status[0]["playerState"];
-        std::string idleReason = (const char*)status[0]["idleReason"];
+        const json_value *status = json_get(entry, "status");
+        if (!status) {
+            return;
+        }
+        if (status->array.size < 1) {
+            msg_Warn( m_module, "Bad payload, got a media status message with less than one session Id");
+            return;
+        }
+        int64_t sessionId = (int64_t) json_get_num(&status->array.entries[0].object,"mediaSessionId");
+        tmp = json_get_str(&status->array.entries[0].object,"playerState");
+        std::string newPlayerState = tmp ? tmp: "";
+        tmp = json_get_str(&status->array.entries[0].object,"idleReason");
+        std::string idleReason = tmp ? tmp: "";
 
         msg_Dbg( m_module, "Player state: %s sessionId: %" PRId64,
-                status[0]["playerState"].operator const char *(),
-                sessionId );
+                 json_get_str(&status->array.entries[0].object,"playerState"),
+                 sessionId );
 
         if (sessionId != 0 && m_mediaSessionId != 0 && m_mediaSessionId != sessionId)
         {
             msg_Warn( m_module, "Ignoring message for a different media session");
-            json_value_free(p_data);
             return;
         }
 
@@ -881,12 +946,15 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
                 setState( Stopping );
             }
             else if (newPlayerState == "PLAYING")
-            {
-                vlc_tick_t currentTime = timeCCToVLC((double) status[0]["currentTime"]);
-                m_cc_time = currentTime;
-                m_cc_time_date = vlc_tick_now();
-
-                setState( Playing );
+            {                
+                if (status->array.size >= 1) {                                
+                    vlc_tick_t currentTime = timeCCToVLC(json_get_num(&status->array.entries[0].object,
+                                                                      "currentTime"));
+                    m_cc_time = currentTime;
+                    m_cc_time_date = vlc_tick_now();
+                    
+                    setState( Playing );
+                }
             }
             else if (newPlayerState == "BUFFERING")
             {
@@ -930,7 +998,7 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
     }
     else if (type == "INVALID_REQUEST")
     {
-        msg_Dbg( m_module, "We sent an invalid request reason:%s", (const char*)(*p_data)["reason"] );
+        msg_Dbg( m_module, "We sent an invalid request reason:%s", json_get_str(entry, "reason"));
     }
     else
     {
@@ -938,14 +1006,16 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
                 msg.payload_utf8().c_str());
     }
 
-    json_value_free(p_data);
 }
 
-void intf_sys_t::processConnectionMessage( const castchannel::CastMessage& msg )
+void intf_sys_t::processConnectionMessage( const castchannel::CastMessage& msg , const struct json_object *entry )
 {
-    json_value *p_data = json_parse(msg.payload_utf8().c_str(), msg.payload_utf8().length());
-    std::string type((*p_data)["type"]);
-    json_value_free(p_data);
+    const struct json_value *value = json_get(entry, msg.payload_utf8().c_str());
+    if (!value) {
+        msg_Err(m_module, "connection message: bad payload");
+        return;
+    }
+    std::string type = json_get_str(&value->object, "type");
 
     if ( type == "CLOSE" )
     {


=====================================
modules/stream_out/chromecast/meson.build
=====================================
@@ -56,11 +56,11 @@ vlc_modules += {
         'chromecast_common.h',
         'chromecast_ctrl.cpp',
         'chromecast_communication.cpp',
-        '../../misc/webservices/json.c',
-        '../../misc/webservices/json.h',
+        '../../demux/json/json.c',
         '../renderer_common.cpp',
         '../renderer_common.hpp') +
         chromecast_proto,
     'dependencies' : [socket_libs, protobuf_dep],
+    'link_with' : vlc_json_lib,
     'enabled': get_option('stream_outputs') and protobuf_dep.found() and protoc.found(),
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/02b197170de07c75a70fa5b414d213ba57b46f56...5cb606cf94cc650938f3b4b06c13c464a2ce9231

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/02b197170de07c75a70fa5b414d213ba57b46f56...5cb606cf94cc650938f3b4b06c13c464a2ce9231
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list