[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