[vlc-commits] acoustid: refactor

Francois Cartegnie git at videolan.org
Fri May 31 15:24:07 CEST 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri May 31 14:43:59 2019 +0200| [cdb7b9d8b21815d6dbe06aed25d9bf3621634e9d] | committer: Francois Cartegnie

acoustid: refactor

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=cdb7b9d8b21815d6dbe06aed25d9bf3621634e9d
---

 modules/misc/Makefile.am               |   1 +
 modules/misc/fingerprinter.c           |   4 +-
 modules/misc/webservices/acoustid.c    | 123 ++++++++------------------------
 modules/misc/webservices/acoustid.h    |   4 +-
 modules/misc/webservices/json_helper.h | 125 +++++++++++++++++++++++++++++++++
 5 files changed, 161 insertions(+), 96 deletions(-)

diff --git a/modules/misc/Makefile.am b/modules/misc/Makefile.am
index affa03f43b..300ef1d961 100644
--- a/modules/misc/Makefile.am
+++ b/modules/misc/Makefile.am
@@ -18,6 +18,7 @@ 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)
diff --git a/modules/misc/fingerprinter.c b/modules/misc/fingerprinter.c
index 8300a692ec..c91f7e4a72 100644
--- a/modules/misc/fingerprinter.c
+++ b/modules/misc/fingerprinter.c
@@ -353,11 +353,11 @@ static void *Run( void *opaque )
                 DoFingerprint( p_fingerprinter, &acoustid_print, psz_uri );
                 free( psz_uri );
 
-                DoAcoustIdWebRequest( VLC_OBJECT(p_fingerprinter), &acoustid_print );
+                acoustid_lookup_fingerprint( VLC_OBJECT(p_fingerprinter), &acoustid_print );
                 fill_metas_with_results( p_data, &acoustid_print );
 
                 for( unsigned j = 0; j < acoustid_print.results.count; j++ )
-                     free_acoustid_result_t( &acoustid_print.results.p_results[j] );
+                     acoustid_result_release( &acoustid_print.results.p_results[j] );
                 if( acoustid_print.results.count )
                     free( acoustid_print.results.p_results );
                 free( acoustid_print.psz_fingerprint );
diff --git a/modules/misc/webservices/acoustid.c b/modules/misc/webservices/acoustid.c
index c816269ce4..c7710a27d1 100644
--- a/modules/misc/webservices/acoustid.c
+++ b/modules/misc/webservices/acoustid.c
@@ -22,17 +22,13 @@
 # include "config.h"
 #endif
 
-#include <vlc_common.h>
-#include <vlc_stream.h>
-#include <limits.h>
-
+#include "json_helper.h"
 #include "acoustid.h"
-#include "json.h"
 
 /*****************************************************************************
  * Requests lifecycle
  *****************************************************************************/
-void free_acoustid_result_t( acoustid_result_t * r )
+void acoustid_result_release( acoustid_result_t * r )
 {
     free( r->psz_id );
     for ( unsigned int i=0; i<r->recordings.count; i++ )
@@ -43,26 +39,15 @@ void free_acoustid_result_t( acoustid_result_t * r )
     free( r->recordings.p_recordings );
 }
 
-static json_value * jsongetbyname( json_value *object, const char *psz_name )
-{
-    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 void parse_artists( json_value *node, acoustid_mb_result_t *record )
+static void parse_artists( const json_value *node, acoustid_mb_result_t *record )
 {
     /* take only main */
-    if ( !node || node->type != json_array || node->u.array.length < 1 ) return;
-    json_value *artistnode = node->u.array.values[ 0 ];
-    json_value *value = jsongetbyname( artistnode, "name" );
-    if ( value && value->type == json_string )
-        record->psz_artist = strdup( value->u.string.ptr );
+    if ( !node || node->type != json_array || node->u.array.length < 1 )
+        return;
+    record->psz_artist = json_dupstring( node->u.array.values[ 0 ], "name" );
 }
 
-static void parse_recordings( vlc_object_t *p_obj, json_value *node, acoustid_result_t *p_result )
+static void parse_recordings( vlc_object_t *p_obj, const json_value *node, 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) );
@@ -72,40 +57,30 @@ static void parse_recordings( vlc_object_t *p_obj, json_value *node, acoustid_re
     for( unsigned int i=0; i<node->u.array.length; i++ )
     {
         acoustid_mb_result_t *record = & p_result->recordings.p_recordings[ i ];
-        json_value *recordnode = node->u.array.values[ i ];
-        if ( !recordnode || recordnode->type != json_object ) break;
-        json_value *value = jsongetbyname( recordnode, "title" );
-        if ( value && value->type == json_string )
-            record->psz_title = strdup( value->u.string.ptr );
-        value = jsongetbyname( recordnode, "id" );
+        const json_value *recordnode = node->u.array.values[ i ];
+        if ( !recordnode || 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 )
         {
             size_t i_len = strlen( value->u.string.ptr );
             i_len = __MIN( i_len, MB_ID_SIZE );
             memcpy( record->s_musicbrainz_id, value->u.string.ptr, i_len );
         }
-        parse_artists( jsongetbyname( recordnode, "artists" ), record );
-        msg_Dbg( p_obj, "recording %d title %s %36s %s", i, record->psz_title, record->s_musicbrainz_id, record->psz_artist );
+        parse_artists( json_getbyname( recordnode, "artists" ), record );
+        msg_Dbg( p_obj, "recording %d title %s %36s %s", i, record->psz_title,
+                 record->s_musicbrainz_id, record->psz_artist );
     }
 }
 
-static bool ParseJson( vlc_object_t *p_obj, const char *psz_buffer, acoustid_results_t *p_results )
+static bool ParseJson( vlc_object_t *p_obj, const void *p_buffer, acoustid_results_t *p_results )
 {
-    json_settings settings;
-    char psz_error[128];
-    memset (&settings, 0, sizeof (json_settings));
-    json_value *root = json_parse_ex( &settings, psz_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;
-    }
-    json_value *node = jsongetbyname( root, "status" );
+    json_value *root = json_parse_document( p_obj, p_buffer );
+    if( !root )
+        return false;
+
+    const json_value *node = json_getbyname( root, "status" );
     if ( !node || node->type != json_string )
     {
         msg_Warn( p_obj, "status node not found or invalid" );
@@ -116,7 +91,7 @@ static bool ParseJson( vlc_object_t *p_obj, const char *psz_buffer, acoustid_res
         msg_Warn( p_obj, "Bad request status" );
         goto error;
     }
-    node = jsongetbyname( root, "results" );
+    node = json_getbyname( root, "results" );
     if ( !node || node->type != json_array )
     {
         msg_Warn( p_obj, "Bad results array or no results" );
@@ -127,17 +102,15 @@ static bool ParseJson( vlc_object_t *p_obj, const char *psz_buffer, acoustid_res
     p_results->count = node->u.array.length;
     for( unsigned int i=0; i<node->u.array.length; i++ )
     {
-        json_value *resultnode = node->u.array.values[i];
+        const json_value *resultnode = node->u.array.values[i];
         if ( resultnode && resultnode->type == json_object )
         {
             acoustid_result_t *p_result = & p_results->p_results[i];
-            json_value *value = jsongetbyname( resultnode, "score" );
+            const json_value *value = json_getbyname( resultnode, "score" );
             if ( value && value->type == json_double )
                 p_result->d_score = value->u.dbl;
-            value = jsongetbyname( resultnode, "id" );
-            if ( value && value->type == json_string )
-                p_result->psz_id = strdup( value->u.string.ptr );
-            parse_recordings( p_obj, jsongetbyname( resultnode, "recordings" ), p_result );
+            p_result->psz_id = json_dupstring( resultnode, "id" );
+            parse_recordings( p_obj, json_getbyname( resultnode, "recordings" ), p_result );
         }
     }
     json_value_free( root );
@@ -148,9 +121,10 @@ error:
     return false;
 }
 
-int DoAcoustIdWebRequest( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data )
+int acoustid_lookup_fingerprint( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data )
 {
-    if ( !p_data->psz_fingerprint ) return VLC_SUCCESS;
+    if ( !p_data->psz_fingerprint )
+        return VLC_SUCCESS;
 
     char *psz_url;
     if( unlikely(asprintf( &psz_url, "https://fingerprint.videolan.org/"
@@ -160,46 +134,11 @@ int DoAcoustIdWebRequest( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data )
          return VLC_EGENERIC;
 
     msg_Dbg( p_obj, "Querying AcoustID from %s", psz_url );
-    bool saved_no_interact = p_obj->no_interact;
-    p_obj->no_interact = true;
-
-    stream_t *p_stream = vlc_stream_NewURL( p_obj, psz_url );
-
+    void *p_buffer = json_retrieve_document( p_obj, psz_url );
     free( psz_url );
-    p_obj->no_interact = saved_no_interact;
-    if ( p_stream == NULL )
+    if( !p_buffer )
         return VLC_EGENERIC;
 
-    stream_t *p_chain = vlc_stream_FilterNew( p_stream, "inflate" );
-    if( p_chain )
-        p_stream = p_chain;
-
-    /* read answer */
-    char *p_buffer = NULL;
-    int i_ret = 0;
-    for( ;; )
-    {
-        int i_read = 65536;
-
-        if( i_ret >= INT_MAX - i_read )
-            break;
-
-        p_buffer = realloc_or_free( p_buffer, 1 + i_ret + i_read );
-        if( unlikely(p_buffer == NULL) )
-        {
-            vlc_stream_Delete( p_stream );
-            return VLC_ENOMEM;
-        }
-
-        i_read = vlc_stream_Read( p_stream, &p_buffer[i_ret], i_read );
-        if( i_read <= 0 )
-            break;
-
-        i_ret += i_read;
-    }
-    vlc_stream_Delete( p_stream );
-    p_buffer[i_ret] = 0;
-
     if ( ParseJson( p_obj, p_buffer, & p_data->results ) )
         msg_Dbg( p_obj, "results count == %d", p_data->results.count );
     else
diff --git a/modules/misc/webservices/acoustid.h b/modules/misc/webservices/acoustid.h
index f2d2f79578..abae220f96 100644
--- a/modules/misc/webservices/acoustid.h
+++ b/modules/misc/webservices/acoustid.h
@@ -55,5 +55,5 @@ struct acoustid_fingerprint_t
 };
 typedef struct acoustid_fingerprint_t acoustid_fingerprint_t;
 
-int DoAcoustIdWebRequest( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data );
-void free_acoustid_result_t( acoustid_result_t * r );
+int acoustid_lookup_fingerprint( vlc_object_t *, acoustid_fingerprint_t * );
+void acoustid_result_release( acoustid_result_t * );
diff --git a/modules/misc/webservices/json_helper.h b/modules/misc/webservices/json_helper.h
new file mode 100644
index 0000000000..52c2d8e57a
--- /dev/null
+++ b/modules/misc/webservices/json_helper.h
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * json_helper.h:
+ *****************************************************************************
+ * Copyright (C) 2012-2019 VLC authors, VideoLabs and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef JSON_HELPER_H
+#define JSON_HELPER_H
+
+#include <vlc_common.h>
+#include <vlc_stream.h>
+
+#include <limits.h>
+
+#include "json.h"
+
+static inline
+const json_value * json_getbyname(const json_value *object, const char *psz_name)
+{
+    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);
+    return (str) ? strdup(str) : NULL;
+}
+
+static inline
+json_value * json_parse_document(vlc_object_t *p_obj, const char *psz_buffer)
+{
+    json_settings settings;
+    char psz_error[128];
+    memset (&settings, 0, sizeof (json_settings));
+    json_value *root = json_parse_ex(&settings, psz_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)
+{
+    bool saved_no_interact = p_obj->no_interact;
+    p_obj->no_interact = true;
+    stream_t *p_stream = vlc_stream_NewURL(p_obj, psz_url);
+
+    p_obj->no_interact = saved_no_interact;
+    if (p_stream == NULL)
+        return NULL;
+
+    stream_t *p_chain = vlc_stream_FilterNew(p_stream, "inflate");
+    if(p_chain)
+        p_stream = p_chain;
+
+    /* read answer */
+    char *p_buffer = NULL;
+    int i_ret = 0;
+    for(;;)
+    {
+        int i_read = 65536;
+
+        if(i_ret >= INT_MAX - i_read)
+            break;
+
+        p_buffer = realloc_or_free(p_buffer, 1 + i_ret + i_read);
+        if(unlikely(p_buffer == NULL))
+        {
+            vlc_stream_Delete(p_stream);
+            return NULL;
+        }
+
+        i_read = vlc_stream_Read(p_stream, &p_buffer[i_ret], i_read);
+        if(i_read <= 0)
+            break;
+
+        i_ret += i_read;
+    }
+    vlc_stream_Delete(p_stream);
+    p_buffer[i_ret] = 0;
+
+    return p_buffer;
+}
+
+#endif



More information about the vlc-commits mailing list