aboutsummaryrefslogtreecommitdiffstats
path: root/src/playlist
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/playlist/asx_playlist_plugin.c3
-rw-r--r--src/playlist/cue_playlist_plugin.c3
-rw-r--r--src/playlist/despotify_playlist_plugin.c3
-rw-r--r--src/playlist/flac_playlist_plugin.c3
-rw-r--r--src/playlist/lastfm_playlist_plugin.c45
-rw-r--r--src/playlist/pls_playlist_plugin.c3
-rw-r--r--src/playlist/rss_playlist_plugin.c3
-rw-r--r--src/playlist/xspf_playlist_plugin.c3
-rw-r--r--src/playlist_any.c15
-rw-r--r--src/playlist_any.h5
-rw-r--r--src/playlist_list.c45
-rw-r--r--src/playlist_list.h7
-rw-r--r--src/playlist_mapper.c27
-rw-r--r--src/playlist_mapper.h5
-rw-r--r--src/playlist_plugin.h10
-rw-r--r--src/playlist_print.c14
-rw-r--r--src/playlist_queue.c14
17 files changed, 116 insertions, 92 deletions
diff --git a/src/playlist/asx_playlist_plugin.c b/src/playlist/asx_playlist_plugin.c
index b711f83f3..298687859 100644
--- a/src/playlist/asx_playlist_plugin.c
+++ b/src/playlist/asx_playlist_plugin.c
@@ -233,7 +233,8 @@ asx_open_stream(struct input_stream *is)
&parser, asx_parser_destroy);
while (true) {
- nbytes = input_stream_read(is, buffer, sizeof(buffer), &error);
+ nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
+ &error);
if (nbytes == 0) {
if (error != NULL) {
g_markup_parse_context_free(context);
diff --git a/src/playlist/cue_playlist_plugin.c b/src/playlist/cue_playlist_plugin.c
index e3619a284..3f2d5b34c 100644
--- a/src/playlist/cue_playlist_plugin.c
+++ b/src/playlist/cue_playlist_plugin.c
@@ -41,7 +41,8 @@ struct cue_playlist {
};
static struct playlist_provider *
-cue_playlist_open_uri(const char *uri)
+cue_playlist_open_uri(const char *uri,
+ G_GNUC_UNUSED GMutex *mutex, G_GNUC_UNUSED GCond *cond)
{
struct cue_playlist *playlist;
FILE *file;
diff --git a/src/playlist/despotify_playlist_plugin.c b/src/playlist/despotify_playlist_plugin.c
index 39448e01f..08a32d79d 100644
--- a/src/playlist/despotify_playlist_plugin.c
+++ b/src/playlist/despotify_playlist_plugin.c
@@ -110,7 +110,8 @@ despotify_playlist_finish(void)
static struct playlist_provider *
-despotify_playlist_open_uri(const char *url)
+despotify_playlist_open_uri(const char *url, G_GNUC_UNUSED GMutex *mutex,
+ G_GNUC_UNUSED GCond *cond)
{
struct despotify_playlist *ctx;
struct despotify_session *session;
diff --git a/src/playlist/flac_playlist_plugin.c b/src/playlist/flac_playlist_plugin.c
index 8adf694ed..e20519435 100644
--- a/src/playlist/flac_playlist_plugin.c
+++ b/src/playlist/flac_playlist_plugin.c
@@ -45,7 +45,8 @@ struct flac_playlist {
};
static struct playlist_provider *
-flac_playlist_open_uri(const char *uri)
+flac_playlist_open_uri(const char *uri,
+ G_GNUC_UNUSED GMutex *mutex, G_GNUC_UNUSED GCond *cond)
{
if (!g_path_is_absolute(uri))
/* only local files supported */
diff --git a/src/playlist/lastfm_playlist_plugin.c b/src/playlist/lastfm_playlist_plugin.c
index 5c803cd99..86113643c 100644
--- a/src/playlist/lastfm_playlist_plugin.c
+++ b/src/playlist/lastfm_playlist_plugin.c
@@ -83,15 +83,14 @@ lastfm_finish(void)
* @return data fetched, or NULL on error. Must be freed with g_free.
*/
static char *
-lastfm_get(const char *url)
+lastfm_get(const char *url, GMutex *mutex, GCond *cond)
{
struct input_stream *input_stream;
GError *error = NULL;
- int ret;
char buffer[4096];
size_t length = 0, nbytes;
- input_stream = input_stream_open(url, &error);
+ input_stream = input_stream_open(url, mutex, cond, &error);
if (input_stream == NULL) {
if (error != NULL) {
g_warning("%s", error->message);
@@ -101,15 +100,9 @@ lastfm_get(const char *url)
return NULL;
}
- while (!input_stream->ready) {
- ret = input_stream_buffer(input_stream, &error);
- if (ret < 0) {
- input_stream_close(input_stream);
- g_warning("%s", error->message);
- g_error_free(error);
- return NULL;
- }
- }
+ g_mutex_lock(mutex);
+
+ input_stream_wait_ready(input_stream);
do {
nbytes = input_stream_read(input_stream, buffer + length,
@@ -124,6 +117,7 @@ lastfm_get(const char *url)
break;
/* I/O error */
+ g_mutex_unlock(mutex);
input_stream_close(input_stream);
return NULL;
}
@@ -131,6 +125,8 @@ lastfm_get(const char *url)
length += nbytes;
} while (length < sizeof(buffer));
+ g_mutex_unlock(mutex);
+
input_stream_close(input_stream);
return g_strndup(buffer, length);
}
@@ -162,7 +158,7 @@ lastfm_find(const char *response, const char *name)
}
static struct playlist_provider *
-lastfm_open_uri(const char *uri)
+lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond)
{
struct lastfm_playlist *playlist;
GError *error = NULL;
@@ -175,7 +171,7 @@ lastfm_open_uri(const char *uri)
"username=", lastfm_config.user, "&"
"passwordmd5=", lastfm_config.md5, "&"
"debug=0&partner=", NULL);
- response = lastfm_get(p);
+ response = lastfm_get(p, mutex, cond);
g_free(p);
if (response == NULL)
return NULL;
@@ -207,7 +203,7 @@ lastfm_open_uri(const char *uri)
NULL);
g_free(escaped_uri);
- response = lastfm_get(p);
+ response = lastfm_get(p, mutex, cond);
g_free(response);
g_free(p);
@@ -229,7 +225,7 @@ lastfm_open_uri(const char *uri)
NULL);
g_free(session);
- playlist->is = input_stream_open(p, &error);
+ playlist->is = input_stream_open(p, mutex, cond, &error);
g_free(p);
if (playlist->is == NULL) {
@@ -243,26 +239,17 @@ lastfm_open_uri(const char *uri)
return NULL;
}
- while (!playlist->is->ready) {
- int ret = input_stream_buffer(playlist->is, &error);
- if (ret < 0) {
- input_stream_close(playlist->is);
- g_free(playlist);
- g_warning("%s", error->message);
- g_error_free(error);
- return NULL;
- }
+ g_mutex_lock(mutex);
- if (ret == 0)
- /* nothing was buffered - wait */
- g_usleep(10000);
- }
+ input_stream_wait_ready(playlist->is);
/* last.fm does not send a MIME type, we have to fake it here
:-( */
g_free(playlist->is->mime);
playlist->is->mime = g_strdup("application/xspf+xml");
+ g_mutex_unlock(mutex);
+
/* parse the XSPF playlist */
playlist->xspf = playlist_list_open_stream(playlist->is, NULL);
diff --git a/src/playlist/pls_playlist_plugin.c b/src/playlist/pls_playlist_plugin.c
index 937f02791..c4e5492af 100644
--- a/src/playlist/pls_playlist_plugin.c
+++ b/src/playlist/pls_playlist_plugin.c
@@ -115,7 +115,8 @@ pls_open_stream(struct input_stream *is)
GString *kf_data = g_string_new("");
do {
- nbytes = input_stream_read(is, buffer, sizeof(buffer), &error);
+ nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
+ &error);
if (nbytes == 0) {
if (error != NULL) {
g_string_free(kf_data, TRUE);
diff --git a/src/playlist/rss_playlist_plugin.c b/src/playlist/rss_playlist_plugin.c
index 9ce3c6abe..6740cba7e 100644
--- a/src/playlist/rss_playlist_plugin.c
+++ b/src/playlist/rss_playlist_plugin.c
@@ -231,7 +231,8 @@ rss_open_stream(struct input_stream *is)
&parser, rss_parser_destroy);
while (true) {
- nbytes = input_stream_read(is, buffer, sizeof(buffer), &error);
+ nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
+ &error);
if (nbytes == 0) {
if (error != NULL) {
g_markup_parse_context_free(context);
diff --git a/src/playlist/xspf_playlist_plugin.c b/src/playlist/xspf_playlist_plugin.c
index 89a4a08a4..17d9040e2 100644
--- a/src/playlist/xspf_playlist_plugin.c
+++ b/src/playlist/xspf_playlist_plugin.c
@@ -253,7 +253,8 @@ xspf_open_stream(struct input_stream *is)
&parser, xspf_parser_destroy);
while (true) {
- nbytes = input_stream_read(is, buffer, sizeof(buffer), &error);
+ nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
+ &error);
if (nbytes == 0) {
if (error != NULL) {
g_markup_parse_context_free(context);
diff --git a/src/playlist_any.c b/src/playlist_any.c
index bed12206a..450ca5932 100644
--- a/src/playlist_any.c
+++ b/src/playlist_any.c
@@ -27,18 +27,20 @@
#include <assert.h>
static struct playlist_provider *
-playlist_open_remote(const char *uri, struct input_stream **is_r)
+playlist_open_remote(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
assert(uri_has_scheme(uri));
- struct playlist_provider *playlist = playlist_list_open_uri(uri);
+ struct playlist_provider *playlist =
+ playlist_list_open_uri(uri, mutex, cond);
if (playlist != NULL) {
*is_r = NULL;
return playlist;
}
GError *error = NULL;
- struct input_stream *is = input_stream_open(uri, &error);
+ struct input_stream *is = input_stream_open(uri, mutex, cond, &error);
if (is == NULL) {
if (error != NULL) {
g_warning("Failed to open %s: %s",
@@ -60,9 +62,10 @@ playlist_open_remote(const char *uri, struct input_stream **is_r)
}
struct playlist_provider *
-playlist_open_any(const char *uri, struct input_stream **is_r)
+playlist_open_any(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
return uri_has_scheme(uri)
- ? playlist_open_remote(uri, is_r)
- : playlist_mapper_open(uri, is_r);
+ ? playlist_open_remote(uri, mutex, cond, is_r)
+ : playlist_mapper_open(uri, mutex, cond, is_r);
}
diff --git a/src/playlist_any.h b/src/playlist_any.h
index 7c13df718..310913de9 100644
--- a/src/playlist_any.h
+++ b/src/playlist_any.h
@@ -20,7 +20,7 @@
#ifndef MPD_PLAYLIST_ANY_H
#define MPD_PLAYLIST_ANY_H
-#include <stdbool.h>
+#include <glib.h>
struct playlist_provider;
struct input_stream;
@@ -35,6 +35,7 @@ struct input_stream;
* freed
*/
struct playlist_provider *
-playlist_open_any(const char *uri, struct input_stream **is_r);
+playlist_open_any(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r);
#endif
diff --git a/src/playlist_list.c b/src/playlist_list.c
index 04c3fa292..1f220eee8 100644
--- a/src/playlist_list.c
+++ b/src/playlist_list.c
@@ -119,7 +119,8 @@ playlist_list_global_finish(void)
}
static struct playlist_provider *
-playlist_list_open_uri_scheme(const char *uri, bool *tried)
+playlist_list_open_uri_scheme(const char *uri, GMutex *mutex, GCond *cond,
+ bool *tried)
{
char *scheme;
struct playlist_provider *playlist = NULL;
@@ -138,7 +139,8 @@ playlist_list_open_uri_scheme(const char *uri, bool *tried)
if (playlist_plugins_enabled[i] && plugin->open_uri != NULL &&
plugin->schemes != NULL &&
string_array_contains(plugin->schemes, scheme)) {
- playlist = playlist_plugin_open_uri(plugin, uri);
+ playlist = playlist_plugin_open_uri(plugin, uri,
+ mutex, cond);
if (playlist != NULL)
break;
@@ -151,7 +153,8 @@ playlist_list_open_uri_scheme(const char *uri, bool *tried)
}
static struct playlist_provider *
-playlist_list_open_uri_suffix(const char *uri, const bool *tried)
+playlist_list_open_uri_suffix(const char *uri, GMutex *mutex, GCond *cond,
+ const bool *tried)
{
const char *suffix;
struct playlist_provider *playlist = NULL;
@@ -168,7 +171,8 @@ playlist_list_open_uri_suffix(const char *uri, const bool *tried)
if (playlist_plugins_enabled[i] && !tried[i] &&
plugin->open_uri != NULL && plugin->suffixes != NULL &&
string_array_contains(plugin->suffixes, suffix)) {
- playlist = playlist_plugin_open_uri(plugin, uri);
+ playlist = playlist_plugin_open_uri(plugin, uri,
+ mutex, cond);
if (playlist != NULL)
break;
}
@@ -178,7 +182,7 @@ playlist_list_open_uri_suffix(const char *uri, const bool *tried)
}
struct playlist_provider *
-playlist_list_open_uri(const char *uri)
+playlist_list_open_uri(const char *uri, GMutex *mutex, GCond *cond)
{
struct playlist_provider *playlist;
/** this array tracks which plugins have already been tried by
@@ -189,9 +193,10 @@ playlist_list_open_uri(const char *uri)
memset(tried, false, sizeof(tried));
- playlist = playlist_list_open_uri_scheme(uri, tried);
+ playlist = playlist_list_open_uri_scheme(uri, mutex, cond, tried);
if (playlist == NULL)
- playlist = playlist_list_open_uri_suffix(uri, tried);
+ playlist = playlist_list_open_uri_suffix(uri, mutex, cond,
+ tried);
return playlist;
}
@@ -278,16 +283,7 @@ playlist_list_open_stream(struct input_stream *is, const char *uri)
const char *suffix;
struct playlist_provider *playlist;
- GError *error = NULL;
- while (!is->ready) {
- int ret = input_stream_buffer(is, &error);
- if (ret < 0) {
- input_stream_close(is);
- g_warning("%s", error->message);
- g_error_free(error);
- return NULL;
- }
- }
+ input_stream_lock_wait_ready(is);
if (is->mime != NULL) {
playlist = playlist_list_open_stream_mime(is);
@@ -322,7 +318,8 @@ playlist_suffix_supported(const char *suffix)
}
struct playlist_provider *
-playlist_list_open_path(const char *path_fs, struct input_stream **is_r)
+playlist_list_open_path(const char *path_fs, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
GError *error = NULL;
const char *suffix;
@@ -335,7 +332,7 @@ playlist_list_open_path(const char *path_fs, struct input_stream **is_r)
if (suffix == NULL || !playlist_suffix_supported(suffix))
return NULL;
- is = input_stream_open(path_fs, &error);
+ is = input_stream_open(path_fs, mutex, cond, &error);
if (is == NULL) {
if (error != NULL) {
g_warning("%s", error->message);
@@ -345,15 +342,7 @@ playlist_list_open_path(const char *path_fs, struct input_stream **is_r)
return NULL;
}
- while (!is->ready) {
- int ret = input_stream_buffer(is, &error);
- if (ret < 0) {
- input_stream_close(is);
- g_warning("%s", error->message);
- g_error_free(error);
- return NULL;
- }
- }
+ input_stream_lock_wait_ready(is);
playlist = playlist_list_open_stream_suffix(is, suffix);
if (playlist != NULL)
diff --git a/src/playlist_list.h b/src/playlist_list.h
index 69eb26b17..4a2485303 100644
--- a/src/playlist_list.h
+++ b/src/playlist_list.h
@@ -20,6 +20,8 @@
#ifndef MPD_PLAYLIST_LIST_H
#define MPD_PLAYLIST_LIST_H
+#include <glib.h>
+
#include <stdbool.h>
struct playlist_provider;
@@ -41,7 +43,7 @@ playlist_list_global_finish(void);
* Opens a playlist by its URI.
*/
struct playlist_provider *
-playlist_list_open_uri(const char *uri);
+playlist_list_open_uri(const char *uri, GMutex *mutex, GCond *cond);
/**
* Opens a playlist from an input stream.
@@ -69,6 +71,7 @@ playlist_suffix_supported(const char *suffix);
* @return a playlist, or NULL on error
*/
struct playlist_provider *
-playlist_list_open_path(const char *path_fs, struct input_stream **is_r);
+playlist_list_open_path(const char *path_fs, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r);
#endif
diff --git a/src/playlist_mapper.c b/src/playlist_mapper.c
index 824b40e0e..13adb80d0 100644
--- a/src/playlist_mapper.c
+++ b/src/playlist_mapper.c
@@ -27,15 +27,16 @@
#include <assert.h>
static struct playlist_provider *
-playlist_open_path(const char *path_fs, struct input_stream **is_r)
+playlist_open_path(const char *path_fs, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
struct playlist_provider *playlist;
- playlist = playlist_list_open_uri(path_fs);
+ playlist = playlist_list_open_uri(path_fs, mutex, cond);
if (playlist != NULL)
*is_r = NULL;
else
- playlist = playlist_list_open_path(path_fs, is_r);
+ playlist = playlist_list_open_path(path_fs, mutex, cond, is_r);
return playlist;
}
@@ -44,7 +45,8 @@ playlist_open_path(const char *path_fs, struct input_stream **is_r)
* Load a playlist from the configured playlist directory.
*/
static struct playlist_provider *
-playlist_open_in_playlist_dir(const char *uri, struct input_stream **is_r)
+playlist_open_in_playlist_dir(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
char *path_fs;
@@ -56,7 +58,8 @@ playlist_open_in_playlist_dir(const char *uri, struct input_stream **is_r)
path_fs = g_build_filename(playlist_directory_fs, uri, NULL);
- struct playlist_provider *playlist = playlist_open_path(path_fs, is_r);
+ struct playlist_provider *playlist =
+ playlist_open_path(path_fs, mutex, cond, is_r);
g_free(path_fs);
return playlist;
@@ -66,7 +69,8 @@ playlist_open_in_playlist_dir(const char *uri, struct input_stream **is_r)
* Load a playlist from the configured music directory.
*/
static struct playlist_provider *
-playlist_open_in_music_dir(const char *uri, struct input_stream **is_r)
+playlist_open_in_music_dir(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
char *path_fs;
@@ -76,25 +80,28 @@ playlist_open_in_music_dir(const char *uri, struct input_stream **is_r)
if (path_fs == NULL)
return NULL;
- struct playlist_provider *playlist = playlist_open_path(path_fs, is_r);
+ struct playlist_provider *playlist =
+ playlist_open_path(path_fs, mutex, cond, is_r);
g_free(path_fs);
return playlist;
}
struct playlist_provider *
-playlist_mapper_open(const char *uri, struct input_stream **is_r)
+playlist_mapper_open(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r)
{
struct playlist_provider *playlist;
if (spl_valid_name(uri)) {
- playlist = playlist_open_in_playlist_dir(uri, is_r);
+ playlist = playlist_open_in_playlist_dir(uri, mutex, cond,
+ is_r);
if (playlist != NULL)
return playlist;
}
if (uri_safe_local(uri)) {
- playlist = playlist_open_in_music_dir(uri, is_r);
+ playlist = playlist_open_in_music_dir(uri, mutex, cond, is_r);
if (playlist != NULL)
return playlist;
}
diff --git a/src/playlist_mapper.h b/src/playlist_mapper.h
index ab8ba982c..9a7187d93 100644
--- a/src/playlist_mapper.h
+++ b/src/playlist_mapper.h
@@ -20,6 +20,8 @@
#ifndef MPD_PLAYLIST_MAPPER_H
#define MPD_PLAYLIST_MAPPER_H
+#include <glib.h>
+
struct input_stream;
/**
@@ -31,6 +33,7 @@ struct input_stream;
* freed
*/
struct playlist_provider *
-playlist_mapper_open(const char *uri, struct input_stream **is_r);
+playlist_mapper_open(const char *uri, GMutex *mutex, GCond *cond,
+ struct input_stream **is_r);
#endif
diff --git a/src/playlist_plugin.h b/src/playlist_plugin.h
index d7d7c7769..a27f651c0 100644
--- a/src/playlist_plugin.h
+++ b/src/playlist_plugin.h
@@ -20,6 +20,8 @@
#ifndef MPD_PLAYLIST_PLUGIN_H
#define MPD_PLAYLIST_PLUGIN_H
+#include <glib.h>
+
#include <stdbool.h>
#include <stddef.h>
@@ -64,7 +66,8 @@ struct playlist_plugin {
* Opens the playlist on the specified URI. This URI has
* either matched one of the schemes or one of the suffixes.
*/
- struct playlist_provider *(*open_uri)(const char *uri);
+ struct playlist_provider *(*open_uri)(const char *uri,
+ GMutex *mutex, GCond *cond);
/**
* Opens the playlist in the specified input stream. It has
@@ -110,9 +113,10 @@ playlist_plugin_finish(const struct playlist_plugin *plugin)
}
static inline struct playlist_provider *
-playlist_plugin_open_uri(const struct playlist_plugin *plugin, const char *uri)
+playlist_plugin_open_uri(const struct playlist_plugin *plugin, const char *uri,
+ GMutex *mutex, GCond *cond)
{
- return plugin->open_uri(uri);
+ return plugin->open_uri(uri, mutex, cond);
}
static inline struct playlist_provider *
diff --git a/src/playlist_print.c b/src/playlist_print.c
index 9962ffc35..a6bf84ccd 100644
--- a/src/playlist_print.c
+++ b/src/playlist_print.c
@@ -171,10 +171,17 @@ playlist_provider_print(struct client *client, const char *uri,
bool
playlist_file_print(struct client *client, const char *uri, bool detail)
{
+ GMutex *mutex = g_mutex_new();
+ GCond *cond = g_cond_new();
+
struct input_stream *is;
- struct playlist_provider *playlist = playlist_open_any(uri, &is);
- if (playlist == NULL)
+ struct playlist_provider *playlist =
+ playlist_open_any(uri, mutex, cond, &is);
+ if (playlist == NULL) {
+ g_cond_free(cond);
+ g_mutex_free(mutex);
return false;
+ }
playlist_provider_print(client, uri, playlist, detail);
playlist_plugin_close(playlist);
@@ -182,5 +189,8 @@ playlist_file_print(struct client *client, const char *uri, bool detail)
if (is != NULL)
input_stream_close(is);
+ g_cond_free(cond);
+ g_mutex_free(mutex);
+
return true;
}
diff --git a/src/playlist_queue.c b/src/playlist_queue.c
index d368fcb23..33885ae21 100644
--- a/src/playlist_queue.c
+++ b/src/playlist_queue.c
@@ -59,10 +59,17 @@ playlist_open_into_queue(const char *uri,
struct playlist *dest, struct player_control *pc,
bool secure)
{
+ GMutex *mutex = g_mutex_new();
+ GCond *cond = g_cond_new();
+
struct input_stream *is;
- struct playlist_provider *playlist = playlist_open_any(uri, &is);
- if (playlist == NULL)
+ struct playlist_provider *playlist =
+ playlist_open_any(uri, mutex, cond, &is);
+ if (playlist == NULL) {
+ g_cond_free(cond);
+ g_mutex_free(mutex);
return PLAYLIST_RESULT_NO_SUCH_LIST;
+ }
enum playlist_result result =
playlist_load_into_queue(uri, playlist, dest, pc, secure);
@@ -71,5 +78,8 @@ playlist_open_into_queue(const char *uri,
if (is != NULL)
input_stream_close(is);
+ g_cond_free(cond);
+ g_mutex_free(mutex);
+
return result;
}