diff options
author | Max Kellermann <max@duempel.org> | 2011-09-14 21:46:41 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2011-09-16 21:22:13 +0200 |
commit | 754f26a97c816781e80500d98f2515ae97836145 (patch) | |
tree | caa7dbaa879b29d018a4559524390670ad33a605 /src/playlist | |
parent | 29241c4f835797f635816a9f37528aa981f722b5 (diff) | |
download | mpd-754f26a97c816781e80500d98f2515ae97836145.tar.gz mpd-754f26a97c816781e80500d98f2515ae97836145.tar.xz mpd-754f26a97c816781e80500d98f2515ae97836145.zip |
input_stream: non-blocking I/O
Add GMutex, GCond attributes which will be used by callers to
conditionally wait on the stream.
Remove the (now-useless) plugin method buffer(), wait on GCond
instead. Lock the input_stream before each method call. Do the same
with the playlist plugins.
Diffstat (limited to '')
-rw-r--r-- | src/playlist/asx_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist/cue_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist/despotify_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist/flac_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist/lastfm_playlist_plugin.c | 45 | ||||
-rw-r--r-- | src/playlist/pls_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist/rss_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist/xspf_playlist_plugin.c | 3 | ||||
-rw-r--r-- | src/playlist_any.c | 15 | ||||
-rw-r--r-- | src/playlist_any.h | 5 | ||||
-rw-r--r-- | src/playlist_list.c | 45 | ||||
-rw-r--r-- | src/playlist_list.h | 7 | ||||
-rw-r--r-- | src/playlist_mapper.c | 27 | ||||
-rw-r--r-- | src/playlist_mapper.h | 5 | ||||
-rw-r--r-- | src/playlist_plugin.h | 10 | ||||
-rw-r--r-- | src/playlist_print.c | 14 | ||||
-rw-r--r-- | src/playlist_queue.c | 14 |
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; } |