585 lines
18 KiB
Diff
585 lines
18 KiB
Diff
Index: plparse/totem-pl-parser.h
|
|
===================================================================
|
|
--- plparse/totem-pl-parser.h (revision 255)
|
|
+++ plparse/totem-pl-parser.h (working copy)
|
|
@@ -248,6 +248,8 @@
|
|
* which can be overridden by inheriting classes
|
|
* @playlist_ended: the generic signal handler for the #TotemPlParser::playlist-ended signal,
|
|
* which can be overridden by inheriting classes
|
|
+ * @parsing_finished: the generic signal handler for the #TotemPlParser::parsing-finished signal,
|
|
+ * which can be overridden by inheriting classes
|
|
*
|
|
* The class structure for the #TotemPlParser type.
|
|
**/
|
|
@@ -263,6 +265,8 @@
|
|
GHashTable *metadata);
|
|
void (*playlist_ended) (TotemPlParser *parser,
|
|
const char *uri);
|
|
+ void (*parsing_finished) (TotemPlParser *parser,
|
|
+ TotemPlParserResult retval);
|
|
};
|
|
|
|
/**
|
|
@@ -349,10 +353,16 @@
|
|
|
|
TotemPlParserResult totem_pl_parser_parse (TotemPlParser *parser,
|
|
const char *url, gboolean fallback);
|
|
+TotemPlParserResult totem_pl_parser_parse_async (TotemPlParser *parser,
|
|
+ const char *url, gboolean fallback);
|
|
TotemPlParserResult totem_pl_parser_parse_with_base (TotemPlParser *parser,
|
|
const char *url,
|
|
const char *base,
|
|
gboolean fallback);
|
|
+TotemPlParserResult totem_pl_parser_parse_with_base_async (TotemPlParser *parser,
|
|
+ const char *url,
|
|
+ const char *base,
|
|
+ gboolean fallback);
|
|
|
|
TotemPlParser *totem_pl_parser_new (void);
|
|
|
|
Index: plparse/totem-pl-parser-private.h
|
|
===================================================================
|
|
--- plparse/totem-pl-parser-private.h (revision 255)
|
|
+++ plparse/totem-pl-parser-private.h (working copy)
|
|
@@ -76,7 +76,12 @@
|
|
{
|
|
GList *ignore_schemes;
|
|
GList *ignore_mimetypes;
|
|
+ GMutex *ignore_mutex;
|
|
|
|
+ GThread *thread;
|
|
+ GAsyncQueue *parse_queue;
|
|
+ gboolean thread_stopping;
|
|
+
|
|
guint recurse_level;
|
|
guint fallback : 1;
|
|
guint recurse : 1;
|
|
Index: plparse/plparser.symbols
|
|
===================================================================
|
|
--- plparse/plparser.symbols (revision 255)
|
|
+++ plparse/plparser.symbols (working copy)
|
|
@@ -14,9 +14,11 @@
|
|
totemplparser_marshal_VOID__STRING_STRING_STRING
|
|
totem_pl_parser_new
|
|
totem_pl_parser_parse
|
|
+totem_pl_parser_parse_async
|
|
totem_pl_parser_parse_date
|
|
totem_pl_parser_parse_duration
|
|
totem_pl_parser_parse_with_base
|
|
+totem_pl_parser_parse_with_base_async
|
|
totem_pl_parser_relative
|
|
totem_pl_parser_result_get_type
|
|
totem_pl_parser_type_get_type
|
|
Index: plparse/totem-pl-parser.c
|
|
===================================================================
|
|
--- plparse/totem-pl-parser.c (revision 255)
|
|
+++ plparse/totem-pl-parser.c (working copy)
|
|
@@ -31,6 +31,9 @@
|
|
*
|
|
* <example>
|
|
* <title>Reading a Playlist</title>
|
|
+ * <para>This example loads a playlist synchronously. To load a playlist asynchronously, however, you simply
|
|
+ * need to use totem_pl_parser_parse_async(), and optionally connect to #TotemPlParser::parsing-finished
|
|
+ * to receive the ultimate #TotemPlParserResult value for the operation.</para>
|
|
* <programlisting>
|
|
* TotemPlParser *pl = totem_pl_parser_new ();
|
|
* g_object_set (pl, "recurse", FALSE, "disable-unsafe", TRUE, NULL);
|
|
@@ -234,6 +237,7 @@
|
|
ENTRY_PARSED,
|
|
PLAYLIST_STARTED,
|
|
PLAYLIST_ENDED,
|
|
+ PARSING_FINISHED,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
@@ -244,12 +248,15 @@
|
|
static void totem_pl_parser_class_init (TotemPlParserClass *klass);
|
|
static void totem_pl_parser_base_class_finalize (TotemPlParserClass *klass);
|
|
static void totem_pl_parser_init (TotemPlParser *parser);
|
|
+static void totem_pl_parser_dispose (GObject *object);
|
|
static void totem_pl_parser_finalize (GObject *object);
|
|
|
|
static void totem_pl_parser_init (TotemPlParser *self);
|
|
static void totem_pl_parser_class_init (TotemPlParserClass *klass);
|
|
static gpointer totem_pl_parser_parent_class = NULL;
|
|
|
|
+#define TOTEM_PL_PARSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TOTEM_TYPE_PL_PARSER, TotemPlParserPrivate))
|
|
+
|
|
GType
|
|
totem_pl_parser_get_type (void)
|
|
{
|
|
@@ -279,9 +286,13 @@
|
|
GParamSpec *pspec;
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
+ if (!g_thread_supported ())
|
|
+ g_thread_init (NULL);
|
|
+
|
|
totem_pl_parser_parent_class = g_type_class_peek_parent (klass);
|
|
g_type_class_add_private (klass, sizeof (TotemPlParserPrivate));
|
|
|
|
+ object_class->dispose = totem_pl_parser_dispose;
|
|
object_class->finalize = totem_pl_parser_finalize;
|
|
object_class->set_property = totem_pl_parser_set_property;
|
|
object_class->get_property = totem_pl_parser_get_property;
|
|
@@ -360,6 +371,7 @@
|
|
NULL, NULL,
|
|
totemplparser_marshal_VOID__STRING_BOXED,
|
|
G_TYPE_NONE, 2, G_TYPE_STRING, TOTEM_TYPE_PL_PARSER_METADATA);
|
|
+
|
|
/**
|
|
* TotemPlParser::playlist-started:
|
|
* @parser: the object which received the signal
|
|
@@ -398,6 +410,24 @@
|
|
g_cclosure_marshal_VOID__STRING,
|
|
G_TYPE_NONE, 1, G_TYPE_STRING);
|
|
|
|
+ /**
|
|
+ * TotemPlParser::parsing-finished:
|
|
+ * @parser: the object which received the signal
|
|
+ * @retval: the #TotemPlParserResult return value from the parse operation
|
|
+ *
|
|
+ * The ::parsing-finished signal is emitted after the parse operation initiated
|
|
+ * by totem_pl_parser_parse() or totem_pl_parser_parse_with_base() has finished
|
|
+ * (successfully or not).
|
|
+ */
|
|
+ totem_pl_parser_table_signals[PARSING_FINISHED] =
|
|
+ g_signal_new ("parsing-finished",
|
|
+ G_TYPE_FROM_CLASS (klass),
|
|
+ G_SIGNAL_RUN_LAST,
|
|
+ G_STRUCT_OFFSET (TotemPlParserClass, parsing_finished),
|
|
+ NULL, NULL,
|
|
+ g_cclosure_marshal_VOID__ENUM,
|
|
+ G_TYPE_NONE, 1, TOTEM_TYPE_PL_PARSER_RESULT);
|
|
+
|
|
/* param specs */
|
|
totem_pl_parser_pspec_pool = g_param_spec_pool_new (FALSE);
|
|
pspec = g_param_spec_string ("url", "url",
|
|
@@ -620,6 +650,26 @@
|
|
return TOTEM_PL_PARSER (g_object_new (TOTEM_TYPE_PL_PARSER, NULL));
|
|
}
|
|
|
|
+typedef struct {
|
|
+ TotemPlParser *parser;
|
|
+ char *playlist_uri;
|
|
+} PlaylistEndedSignalData;
|
|
+
|
|
+static gboolean
|
|
+emit_playlist_ended_signal (PlaylistEndedSignalData *data)
|
|
+{
|
|
+ g_signal_emit (data->parser,
|
|
+ totem_pl_parser_table_signals[PLAYLIST_ENDED],
|
|
+ 0, data->playlist_uri);
|
|
+
|
|
+ /* Free the data */
|
|
+ g_object_unref (data->parser);
|
|
+ g_free (data->playlist_uri);
|
|
+ g_free (data);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
/**
|
|
* totem_pl_parser_playlist_end:
|
|
* @parser: a #TotemPlParser
|
|
@@ -631,9 +681,13 @@
|
|
void
|
|
totem_pl_parser_playlist_end (TotemPlParser *parser, const char *playlist_uri)
|
|
{
|
|
- g_signal_emit (G_OBJECT (parser),
|
|
- totem_pl_parser_table_signals[PLAYLIST_ENDED],
|
|
- 0, playlist_uri);
|
|
+ PlaylistEndedSignalData *data;
|
|
+
|
|
+ data = g_new (PlaylistEndedSignalData, 1);
|
|
+ data->parser = g_object_ref (parser);
|
|
+ data->playlist_uri = g_strdup (playlist_uri);
|
|
+
|
|
+ g_idle_add ((GSourceFunc) emit_playlist_ended_signal, data);
|
|
}
|
|
|
|
static char *
|
|
@@ -1057,25 +1111,70 @@
|
|
totem_pl_parser_init (TotemPlParser *parser)
|
|
{
|
|
parser->priv = G_TYPE_INSTANCE_GET_PRIVATE (parser, TOTEM_TYPE_PL_PARSER, TotemPlParserPrivate);
|
|
+ parser->priv->ignore_mutex = g_mutex_new ();
|
|
}
|
|
|
|
static void
|
|
+totem_pl_parser_dispose (GObject *object)
|
|
+{
|
|
+ TotemPlParserPrivate *priv = TOTEM_PL_PARSER_GET_PRIVATE (object);
|
|
+
|
|
+ /* Tell the thread we're stopping */
|
|
+ priv->thread_stopping = TRUE;
|
|
+
|
|
+ /* Wait for the thread to finish */
|
|
+ if (priv->thread != NULL)
|
|
+ g_thread_join (priv->thread);
|
|
+ priv->thread = NULL;
|
|
+
|
|
+ /* Free the job queue */
|
|
+ if (priv->parse_queue != NULL)
|
|
+ g_async_queue_unref (priv->parse_queue);
|
|
+ priv->parse_queue = NULL;
|
|
+
|
|
+ G_OBJECT_CLASS (totem_pl_parser_parent_class)->dispose (object);
|
|
+}
|
|
+
|
|
+static void
|
|
totem_pl_parser_finalize (GObject *object)
|
|
{
|
|
- TotemPlParser *parser = TOTEM_PL_PARSER (object);
|
|
+ TotemPlParserPrivate *priv = TOTEM_PL_PARSER_GET_PRIVATE (object);
|
|
|
|
g_return_if_fail (object != NULL);
|
|
- g_return_if_fail (parser->priv != NULL);
|
|
+ g_return_if_fail (priv != NULL);
|
|
|
|
- g_list_foreach (parser->priv->ignore_schemes, (GFunc) g_free, NULL);
|
|
- g_list_free (parser->priv->ignore_schemes);
|
|
+ g_list_foreach (priv->ignore_schemes, (GFunc) g_free, NULL);
|
|
+ g_list_free (priv->ignore_schemes);
|
|
|
|
- g_list_foreach (parser->priv->ignore_mimetypes, (GFunc) g_free, NULL);
|
|
- g_list_free (parser->priv->ignore_mimetypes);
|
|
+ g_list_foreach (priv->ignore_mimetypes, (GFunc) g_free, NULL);
|
|
+ g_list_free (priv->ignore_mimetypes);
|
|
|
|
+ g_mutex_free (priv->ignore_mutex);
|
|
+
|
|
G_OBJECT_CLASS (totem_pl_parser_parent_class)->finalize (object);
|
|
}
|
|
|
|
+typedef struct {
|
|
+ TotemPlParser *parser;
|
|
+ guint signal_id;
|
|
+ char *url;
|
|
+ GHashTable *metadata;
|
|
+} EntryParsedSignalData;
|
|
+
|
|
+static gboolean
|
|
+emit_entry_parsed_signal (EntryParsedSignalData *data)
|
|
+{
|
|
+ g_signal_emit (data->parser, data->signal_id, 0, data->url, data->metadata);
|
|
+
|
|
+ /* Free the data */
|
|
+ g_object_unref (data->parser);
|
|
+ g_free (data->url);
|
|
+ g_hash_table_unref (data->metadata);
|
|
+ g_free (data);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
static void
|
|
totem_pl_parser_add_url_valist (TotemPlParser *parser,
|
|
const gchar *first_property_name,
|
|
@@ -1188,15 +1287,21 @@
|
|
}
|
|
|
|
if (g_hash_table_size (metadata) > 0 || url != NULL) {
|
|
- if (is_playlist == FALSE) {
|
|
- g_signal_emit (G_OBJECT (parser),
|
|
- totem_pl_parser_table_signals[ENTRY_PARSED],
|
|
- 0, url, metadata);
|
|
- } else {
|
|
- g_signal_emit (G_OBJECT (parser),
|
|
- totem_pl_parser_table_signals[PLAYLIST_STARTED],
|
|
- 0, url, metadata);
|
|
- }
|
|
+ EntryParsedSignalData *data;
|
|
+
|
|
+ /* Make sure to emit the signals asynchronously, as we could be in the main loop
|
|
+ * *or* a worker thread at this point. */
|
|
+ data = g_new (EntryParsedSignalData, 1);
|
|
+ data->parser = g_object_ref (parser);
|
|
+ data->url = g_strdup (url);
|
|
+ data->metadata = g_hash_table_ref (metadata);
|
|
+
|
|
+ if (is_playlist == FALSE)
|
|
+ data->signal_id = totem_pl_parser_table_signals[ENTRY_PARSED];
|
|
+ else
|
|
+ data->signal_id = totem_pl_parser_table_signals[PLAYLIST_STARTED];
|
|
+
|
|
+ g_idle_add ((GSourceFunc) emit_entry_parsed_signal, data);
|
|
}
|
|
|
|
g_hash_table_unref (metadata);
|
|
@@ -1275,15 +1380,23 @@
|
|
{
|
|
GList *l;
|
|
|
|
- if (parser->priv->ignore_schemes == NULL)
|
|
+ g_mutex_lock (parser->priv->ignore_mutex);
|
|
+
|
|
+ if (parser->priv->ignore_schemes == NULL) {
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
return FALSE;
|
|
+ }
|
|
|
|
for (l = parser->priv->ignore_schemes; l != NULL; l = l->next) {
|
|
const char *scheme = l->data;
|
|
- if (g_file_has_uri_scheme (file, scheme) != FALSE)
|
|
+ if (g_file_has_uri_scheme (file, scheme) != FALSE) {
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
return TRUE;
|
|
+ }
|
|
}
|
|
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
+
|
|
return FALSE;
|
|
}
|
|
|
|
@@ -1293,16 +1406,24 @@
|
|
{
|
|
GList *l;
|
|
|
|
- if (parser->priv->ignore_mimetypes == NULL)
|
|
+ g_mutex_lock (parser->priv->ignore_mutex);
|
|
+
|
|
+ if (parser->priv->ignore_mimetypes == NULL) {
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
return FALSE;
|
|
+ }
|
|
|
|
for (l = parser->priv->ignore_mimetypes; l != NULL; l = l->next)
|
|
{
|
|
const char *item = l->data;
|
|
- if (strcmp (mimetype, item) == 0)
|
|
+ if (strcmp (mimetype, item) == 0) {
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
return TRUE;
|
|
+ }
|
|
}
|
|
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
+
|
|
return FALSE;
|
|
}
|
|
|
|
@@ -1596,6 +1717,70 @@
|
|
return ret;
|
|
}
|
|
|
|
+typedef struct {
|
|
+ char *url;
|
|
+ char *base;
|
|
+ gboolean fallback;
|
|
+ TotemPlParserResult retval;
|
|
+ TotemPlParser *parser;
|
|
+} ParseQueueItem;
|
|
+
|
|
+static void
|
|
+parse_queue_item_free (ParseQueueItem *item)
|
|
+{
|
|
+ g_free (item->url);
|
|
+ g_free (item->base);
|
|
+ g_object_unref (item->parser);
|
|
+
|
|
+ g_free (item);
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+totem_pl_parser_thread_job_finished (ParseQueueItem *queue_item)
|
|
+{
|
|
+ g_signal_emit (queue_item->parser, totem_pl_parser_table_signals[PARSING_FINISHED], 0, queue_item->retval);
|
|
+ parse_queue_item_free (queue_item);
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static gpointer
|
|
+totem_pl_parser_thread_main (TotemPlParser *parser)
|
|
+{
|
|
+ while (parser->priv->thread_stopping == FALSE) {
|
|
+ GFile *file, *base_file;
|
|
+ TotemPlParserResult retval;
|
|
+ ParseQueueItem *queue_item;
|
|
+
|
|
+ /* Get a job off the queue */
|
|
+ queue_item = g_async_queue_pop (parser->priv->parse_queue);
|
|
+
|
|
+ /* Start parsing it */
|
|
+ file = g_file_new_for_uri (queue_item->url);
|
|
+ base_file = NULL;
|
|
+
|
|
+ if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE) {
|
|
+ g_object_unref (file);
|
|
+ retval = TOTEM_PL_PARSER_RESULT_UNHANDLED;
|
|
+ } else {
|
|
+ parser->priv->recurse_level = 0;
|
|
+ parser->priv->fallback = queue_item->fallback != FALSE;
|
|
+ if (queue_item->base != NULL)
|
|
+ base_file = g_file_new_for_uri (queue_item->base);
|
|
+ retval = totem_pl_parser_parse_internal (parser, file, base_file);
|
|
+
|
|
+ g_object_unref (file);
|
|
+ if (base_file != NULL)
|
|
+ g_object_unref (base_file);
|
|
+ }
|
|
+
|
|
+ /* Emit the "parsing-finished" signal for this job from the main thread */
|
|
+ queue_item->retval = retval;
|
|
+ g_idle_add ((GSourceFunc) totem_pl_parser_thread_job_finished, queue_item);
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
/**
|
|
* totem_pl_parser_parse_with_base:
|
|
* @parser: a #TotemPlParser
|
|
@@ -1605,8 +1790,14 @@
|
|
* end of the playlist on parse failure
|
|
*
|
|
* Parses a playlist given by the absolute URL @url, using
|
|
- * @base to resolve relative paths where appropriate.
|
|
+ * @base to resolve relative paths where appropriate. This method is
|
|
+ * synchronous, and will block on (e.g.) network requests to slow
|
|
+ * servers. totem_pl_parser_parse_with_base_async() is recommended instead.
|
|
*
|
|
+ * This function will return %TOTEM_PL_PARSER_RESULT_SUCCESS on success,
|
|
+ * and either %TOTEM_PL_PARSER_RESULT_UNHANDLED or
|
|
+ * %TOTEM_PL_PARSER_RESULT_ERROR if the parameters were invalid.
|
|
+ *
|
|
* Return value: a #TotemPlParserResult
|
|
**/
|
|
TotemPlParserResult
|
|
@@ -1618,8 +1809,7 @@
|
|
|
|
g_return_val_if_fail (TOTEM_IS_PL_PARSER (parser), TOTEM_PL_PARSER_RESULT_UNHANDLED);
|
|
g_return_val_if_fail (url != NULL, TOTEM_PL_PARSER_RESULT_UNHANDLED);
|
|
- g_return_val_if_fail (strstr (url, "://") != NULL,
|
|
- TOTEM_PL_PARSER_RESULT_ERROR);
|
|
+ g_return_val_if_fail (strstr (url, "://") != NULL, TOTEM_PL_PARSER_RESULT_ERROR);
|
|
|
|
file = g_file_new_for_uri (url);
|
|
base_file = NULL;
|
|
@@ -1643,14 +1833,77 @@
|
|
}
|
|
|
|
/**
|
|
+ * totem_pl_parser_parse_with_base_async:
|
|
+ * @parser: a #TotemPlParser
|
|
+ * @url: the URL of the playlist to parse
|
|
+ * @base: the base path for relative filenames
|
|
+ * @fallback: %TRUE if the parser should add the playlist URL to the
|
|
+ * end of the playlist on parse failure
|
|
+ *
|
|
+ * Starts asynchronous parsing of a playlist given by the absolute URL @url,
|
|
+ * using @base to resolve relative paths where appropriate.
|
|
+ *
|
|
+ * This method is asynchronous, and #TotemPlParser::parsing-finished will be
|
|
+ * emitted once parsing is finished (successfully or not).
|
|
+ *
|
|
+ * This function will return %TOTEM_PL_PARSER_RESULT_SUCCESS if the job
|
|
+ * was successfully added to the parse queue, and either
|
|
+ * %TOTEM_PL_PARSER_RESULT_UNHANDLED or %TOTEM_PL_PARSER_RESULT_ERROR
|
|
+ * if the parameters were invalid.
|
|
+ *
|
|
+ * Return value: a #TotemPlParserResult
|
|
+ **/
|
|
+TotemPlParserResult
|
|
+totem_pl_parser_parse_with_base_async (TotemPlParser *parser, const char *url,
|
|
+ const char *base, gboolean fallback)
|
|
+{
|
|
+ ParseQueueItem *queue_item;
|
|
+
|
|
+ g_return_val_if_fail (TOTEM_IS_PL_PARSER (parser), TOTEM_PL_PARSER_RESULT_UNHANDLED);
|
|
+ g_return_val_if_fail (url != NULL, TOTEM_PL_PARSER_RESULT_UNHANDLED);
|
|
+ g_return_val_if_fail (strstr (url, "://") != NULL, TOTEM_PL_PARSER_RESULT_ERROR);
|
|
+
|
|
+ if (parser->priv->thread == NULL) {
|
|
+ GError *error = NULL;
|
|
+
|
|
+ /* Create the worker thread */
|
|
+ parser->priv->parse_queue = g_async_queue_new_full ((GDestroyNotify) parse_queue_item_free);
|
|
+ parser->priv->thread = g_thread_create ((GThreadFunc) totem_pl_parser_thread_main, parser, TRUE, &error);
|
|
+
|
|
+ if (error != NULL) {
|
|
+ g_warning ("Failed to create TotemPlParser worker thread: %s", error->message);
|
|
+ g_async_queue_unref (parser->priv->parse_queue);
|
|
+ g_error_free (error);
|
|
+
|
|
+ return TOTEM_PL_PARSER_RESULT_ERROR;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Thread already exists, so add the parse job to its queue */
|
|
+ queue_item = g_new (ParseQueueItem, 1);
|
|
+ queue_item->url = g_strdup (url);
|
|
+ queue_item->base = g_strdup (base);
|
|
+ queue_item->fallback = fallback;
|
|
+ queue_item->parser = g_object_ref (parser);
|
|
+
|
|
+ g_async_queue_push (parser->priv->parse_queue, queue_item);
|
|
+
|
|
+ return TOTEM_PL_PARSER_RESULT_SUCCESS;
|
|
+}
|
|
+
|
|
+/**
|
|
* totem_pl_parser_parse:
|
|
* @parser: a #TotemPlParser
|
|
* @url: the URL of the playlist to parse
|
|
* @fallback: %TRUE if the parser should add the playlist URL to the
|
|
* end of the playlist on parse failure
|
|
*
|
|
- * Parses a playlist given by the absolute URL @url.
|
|
+ * Parses a playlist given by the absolute URL @url. This method is
|
|
+ * synchronous, and will block on (e.g.) network requests to slow
|
|
+ * servers. totem_pl_parser_parse_async() is recommended instead.
|
|
*
|
|
+ * Return values are as totem_pl_parser_parse_with_base().
|
|
+ *
|
|
* Return value: a #TotemPlParserResult
|
|
**/
|
|
TotemPlParserResult
|
|
@@ -1661,6 +1914,29 @@
|
|
}
|
|
|
|
/**
|
|
+ * totem_pl_parser_parse_async:
|
|
+ * @parser: a #TotemPlParser
|
|
+ * @url: the URL of the playlist to parse
|
|
+ * @fallback: %TRUE if the parser should add the playlist URL to the
|
|
+ * end of the playlist on parse failure
|
|
+ *
|
|
+ * Starts asynchronous parsing of a playlist given by the absolute URL @url.
|
|
+ *
|
|
+ * This method is asynchronous, and #TotemPlParser::parsing-finished will be
|
|
+ * emitted once parsing is finished (successfully or not).
|
|
+ *
|
|
+ * Return values are as totem_pl_parser_parse_with_base_async().
|
|
+ *
|
|
+ * Return value: a #TotemPlParserResult
|
|
+ **/
|
|
+TotemPlParserResult
|
|
+totem_pl_parser_parse_async (TotemPlParser *parser, const char *url,
|
|
+ gboolean fallback)
|
|
+{
|
|
+ return totem_pl_parser_parse_with_base_async (parser, url, NULL, fallback);
|
|
+}
|
|
+
|
|
+/**
|
|
* totem_pl_parser_add_ignored_scheme:
|
|
* @parser: a #TotemPlParser
|
|
* @scheme: the scheme to ignore
|
|
@@ -1676,11 +1952,15 @@
|
|
|
|
g_return_if_fail (TOTEM_IS_PL_PARSER (parser));
|
|
|
|
+ g_mutex_lock (parser->priv->ignore_mutex);
|
|
+
|
|
s = g_strdup (scheme);
|
|
if (s[strlen (s) - 1] == ':')
|
|
s[strlen (s) - 1] = '\0';
|
|
parser->priv->ignore_schemes = g_list_prepend
|
|
(parser->priv->ignore_schemes, s);
|
|
+
|
|
+ g_mutex_unlock (parser->priv->ignore_mutex);
|
|
}
|
|
|
|
/**
|