mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 23:32:04 +02:00
Compare commits
3 Commits
playlistab
...
696b9a2d2e
Author | SHA1 | Date | |
---|---|---|---|
|
696b9a2d2e | ||
|
edd3d5b8f1 | ||
|
7821b5bc20 |
@@ -642,6 +642,18 @@ clapper_app_application_command_line (GApplication *app, GApplicationCommandLine
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_is_claps_file (GFile *file)
|
||||
{
|
||||
gchar *basename = g_file_get_basename (file);
|
||||
gboolean is_claps;
|
||||
|
||||
is_claps = (basename && g_str_has_suffix (basename, ".claps"));
|
||||
g_free (basename);
|
||||
|
||||
return is_claps;
|
||||
}
|
||||
|
||||
static void
|
||||
add_item_from_file (GFile *file, ClapperQueue *queue)
|
||||
{
|
||||
@@ -654,6 +666,51 @@ add_item_from_file (GFile *file, ClapperQueue *queue)
|
||||
gst_object_unref (item);
|
||||
}
|
||||
|
||||
static void
|
||||
add_items_from_claps_file (GFile *file, ClapperQueue *queue)
|
||||
{
|
||||
GDataInputStream *dstream = NULL;
|
||||
GFileInputStream *stream;
|
||||
GError *error = NULL;
|
||||
gchar *line;
|
||||
|
||||
if (!(stream = g_file_read (file, NULL, &error)))
|
||||
goto finish;
|
||||
|
||||
dstream = g_data_input_stream_new (G_INPUT_STREAM (stream));
|
||||
|
||||
while ((line = g_data_input_stream_read_line (
|
||||
dstream, NULL, NULL, &error))) {
|
||||
g_strstrip (line);
|
||||
|
||||
if (strlen (line) > 0) {
|
||||
GFile *tmp_file = gst_uri_is_valid (line)
|
||||
? g_file_new_for_uri (line)
|
||||
: g_file_new_for_path (line);
|
||||
|
||||
if (_is_claps_file (tmp_file))
|
||||
add_items_from_claps_file (tmp_file, queue);
|
||||
else
|
||||
add_item_from_file (tmp_file, queue);
|
||||
|
||||
g_object_unref (tmp_file);
|
||||
}
|
||||
|
||||
g_free (line);
|
||||
}
|
||||
|
||||
finish:
|
||||
if (error) {
|
||||
GST_ERROR ("Could not read \".claps\" file, reason: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
if (stream) {
|
||||
g_input_stream_close (G_INPUT_STREAM (stream), NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
g_clear_object (&dstream);
|
||||
}
|
||||
|
||||
static void
|
||||
add_item_with_subtitles (GFile *media_file,
|
||||
GFile *subs_file, ClapperQueue *queue)
|
||||
@@ -722,8 +779,12 @@ clapper_app_application_open (GApplication *app,
|
||||
if (!handled) {
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_files; ++i)
|
||||
add_item_from_file (files[i], queue);
|
||||
for (i = 0; i < n_files; ++i) {
|
||||
if (_is_claps_file (files[i]))
|
||||
add_items_from_claps_file (files[i], queue);
|
||||
else
|
||||
add_item_from_file (files[i], queue);
|
||||
}
|
||||
}
|
||||
|
||||
add_only = (g_strcmp0 (hint, "add-only") == 0);
|
||||
|
@@ -29,9 +29,6 @@ G_BEGIN_DECLS
|
||||
G_GNUC_INTERNAL
|
||||
ClapperHarvest * clapper_harvest_new (void);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_harvest_set_enhancer_in_caps (ClapperHarvest *harvest, ClapperEnhancerProxy *proxy);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean clapper_harvest_unpack (ClapperHarvest *harvest, GstBuffer **buffer, gsize *buf_size, GstCaps **caps, GstTagList **tags, GstToc **toc, GstStructure **headers);
|
||||
|
||||
|
@@ -94,13 +94,6 @@ clapper_harvest_new (void)
|
||||
return harvest;
|
||||
}
|
||||
|
||||
void
|
||||
clapper_harvest_set_enhancer_in_caps (ClapperHarvest *self, ClapperEnhancerProxy *proxy)
|
||||
{
|
||||
gst_caps_set_simple (self->caps, "enhancer", G_TYPE_STRING,
|
||||
clapper_enhancer_proxy_get_module_name (proxy), NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clapper_harvest_unpack (ClapperHarvest *self,
|
||||
GstBuffer **buffer, gsize *buf_size, GstCaps **caps,
|
||||
@@ -228,6 +221,7 @@ clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
|
||||
gchar *filename;
|
||||
const gchar *data, *read_str;
|
||||
const guint8 *buf_data;
|
||||
guint8 *buf_copy;
|
||||
gsize buf_size;
|
||||
gint64 epoch_cached, epoch_now = 0;
|
||||
gdouble exp_seconds;
|
||||
@@ -287,10 +281,10 @@ clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Read caps */
|
||||
/* Read media type */
|
||||
read_str = clapper_cache_read_string (&data);
|
||||
if (G_UNLIKELY (read_str == NULL)) {
|
||||
GST_ERROR_OBJECT (self, "Could not read caps from cache file");
|
||||
GST_ERROR_OBJECT (self, "Could not read media type from cache file");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@@ -302,12 +296,9 @@ clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
|
||||
}
|
||||
|
||||
/* Fill harvest */
|
||||
if (!(self->caps = gst_caps_from_string (read_str))) {
|
||||
GST_ERROR_OBJECT (self, "Could not construct caps from cache");
|
||||
buf_copy = g_memdup2 (buf_data, buf_size);
|
||||
if (!clapper_harvest_fill (self, read_str, buf_copy, buf_size))
|
||||
goto finish;
|
||||
}
|
||||
self->buffer = gst_buffer_new_memdup (buf_data, buf_size);
|
||||
self->buf_size = buf_size;
|
||||
|
||||
/* Read tags */
|
||||
read_str = clapper_cache_read_string (&data);
|
||||
@@ -341,6 +332,7 @@ clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
|
||||
const GstStructure *config, GUri *uri)
|
||||
{
|
||||
GByteArray *bytes;
|
||||
const GstStructure *caps_structure;
|
||||
gchar *filename, *temp_str = NULL;
|
||||
gboolean data_ok = TRUE;
|
||||
|
||||
@@ -374,13 +366,12 @@ clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
|
||||
clapper_cache_store_string (bytes, temp_str); // NULL when no config
|
||||
g_clear_pointer (&temp_str, g_free);
|
||||
|
||||
/* Store caps */
|
||||
temp_str = gst_caps_to_string (self->caps);
|
||||
if (G_LIKELY (temp_str != NULL)) {
|
||||
clapper_cache_store_string (bytes, temp_str);
|
||||
g_clear_pointer (&temp_str, g_free);
|
||||
/* Store media type */
|
||||
caps_structure = gst_caps_get_structure (self->caps, 0);
|
||||
if (G_LIKELY (caps_structure != NULL)) {
|
||||
clapper_cache_store_string (bytes, gst_structure_get_name (caps_structure));
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self, "Cannot cache caps");
|
||||
GST_ERROR_OBJECT (self, "Cannot cache empty caps");
|
||||
data_ok = FALSE;
|
||||
}
|
||||
|
||||
@@ -443,15 +434,11 @@ clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
|
||||
*
|
||||
* Commonly used media types are:
|
||||
*
|
||||
* * `application/dash+xml` - DASH manifest
|
||||
* * `application/dash+xml`
|
||||
*
|
||||
* * `application/x-hls` - HLS manifest
|
||||
* * `application/x-hls`
|
||||
*
|
||||
* * `text/x-uri` - direct media URI
|
||||
*
|
||||
* * `text/uri-list` - playlist of URIs
|
||||
*
|
||||
* * `application/clapper-playlist` - custom playlist format
|
||||
* * `text/uri-list`
|
||||
*
|
||||
* Returns: %TRUE when filled successfully, %FALSE if taken data was empty.
|
||||
*
|
||||
@@ -472,7 +459,6 @@ clapper_harvest_fill (ClapperHarvest *self, const gchar *media_type, gpointer da
|
||||
if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG) {
|
||||
gboolean is_printable = (strcmp (media_type, "application/dash+xml") == 0)
|
||||
|| (strcmp (media_type, "application/x-hls") == 0)
|
||||
|| (strcmp (media_type, "text/x-uri") == 0)
|
||||
|| (strcmp (media_type, "text/uri-list") == 0);
|
||||
|
||||
if (is_printable) {
|
||||
|
@@ -202,12 +202,6 @@ clapper_media_item_get_id (ClapperMediaItem *self)
|
||||
return self->id;
|
||||
}
|
||||
|
||||
/* FIXME: 1.0:
|
||||
* Consider change to be transfer-full and just return latest data from redirects
|
||||
* list (alternatively expose redirect URI). This should make it possible to work
|
||||
* with enhancers that would benefit from knowledge about URI changes
|
||||
* (e.g "Recall" could read actual media instead of playlist file).
|
||||
*/
|
||||
/**
|
||||
* clapper_media_item_get_uri:
|
||||
* @item: a #ClapperMediaItem
|
||||
@@ -697,8 +691,6 @@ gboolean
|
||||
clapper_media_item_update_from_item (ClapperMediaItem *self, ClapperMediaItem *other_item,
|
||||
ClapperPlayer *player)
|
||||
{
|
||||
gboolean title_changed = FALSE;
|
||||
|
||||
if (!clapper_media_item_set_redirect_uri (self, clapper_media_item_get_uri (other_item)))
|
||||
return FALSE;
|
||||
|
||||
@@ -707,30 +699,8 @@ clapper_media_item_update_from_item (ClapperMediaItem *self, ClapperMediaItem *o
|
||||
if (other_item->tags)
|
||||
clapper_media_item_update_from_tag_list (self, other_item->tags, player);
|
||||
|
||||
/* Since its redirect now, we have to update title to describe new file instead of
|
||||
* being a playlist title. If other item had parsed title, it also means that tags
|
||||
* did not contain it, thus we have to manually update it and notify. */
|
||||
if (other_item->title_is_parsed) {
|
||||
GST_OBJECT_LOCK (self);
|
||||
title_changed = g_set_str (&self->title, other_item->title);
|
||||
self->title_is_parsed = TRUE;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (other_item);
|
||||
|
||||
if (title_changed) {
|
||||
ClapperReactableItemUpdatedFlags flags = CLAPPER_REACTABLE_ITEM_UPDATED_TITLE;
|
||||
ClapperFeaturesManager *features_manager;
|
||||
|
||||
clapper_app_bus_post_prop_notify (player->app_bus, GST_OBJECT_CAST (self), param_specs[PROP_TITLE]);
|
||||
|
||||
if (player->reactables_manager)
|
||||
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
|
||||
if ((features_manager = clapper_player_get_features_manager (player)))
|
||||
clapper_features_manager_trigger_item_updated (features_manager, self);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@@ -873,20 +873,8 @@ _handle_element_msg (GstMessage *msg, ClapperPlayer *player)
|
||||
updated = clapper_media_item_update_from_item (playlist_item, active_item, player);
|
||||
gst_object_unref (active_item);
|
||||
|
||||
if (!updated) {
|
||||
GstMessage *msg;
|
||||
GError *error;
|
||||
|
||||
error = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
|
||||
"Detected infinite redirection in playlist");
|
||||
msg = gst_message_new_error (GST_OBJECT (player), error, NULL);
|
||||
|
||||
_handle_error_msg (msg, player);
|
||||
|
||||
g_error_free (error);
|
||||
gst_message_unref (msg);
|
||||
} else if (n_items > 1) {
|
||||
/* Forward to append remaining items (must be done from main thread) */
|
||||
/* Forward to append remaining items (must be done from main thread) */
|
||||
if (updated && n_items > 1) {
|
||||
clapper_app_bus_post_insert_playlist (player->app_bus,
|
||||
GST_OBJECT_CAST (player),
|
||||
GST_OBJECT_CAST (playlist_item),
|
||||
|
@@ -39,7 +39,6 @@
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/tag/tag.h>
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
#include "clapper-discoverer.h"
|
||||
@@ -129,9 +128,8 @@ _run_discovery (ClapperDiscoverer *self)
|
||||
ClapperMediaItem *item;
|
||||
ClapperQueue *queue;
|
||||
ClapperDiscovererDiscoveryMode discovery_mode;
|
||||
GstTagList *tags;
|
||||
const gchar *uri;
|
||||
gboolean empty_tags, success = FALSE;
|
||||
gboolean success = FALSE;
|
||||
|
||||
if (self->pending_items->len == 0) {
|
||||
GST_DEBUG_OBJECT (self, "No more pending items");
|
||||
@@ -159,16 +157,6 @@ _run_discovery (ClapperDiscoverer *self)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
tags = clapper_media_item_get_tags (item);
|
||||
empty_tags = gst_tag_list_is_empty (tags);
|
||||
gst_tag_list_unref (tags);
|
||||
|
||||
if (!empty_tags) {
|
||||
GST_DEBUG_OBJECT (self, "Queued %" GST_PTR_FORMAT
|
||||
" already has tags, ignoring discovery", item);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
uri = clapper_media_item_get_uri (item);
|
||||
GST_DEBUG_OBJECT (self, "Starting discovery of %"
|
||||
GST_PTR_FORMAT "(%s)", item, uri);
|
||||
|
@@ -106,10 +106,9 @@ clapper_enhancer_director_extract_in_thread (ClapperEnhancerDirectorData *data)
|
||||
|
||||
/* We are done with extractable, but keep harvest and try to cache it */
|
||||
if (success) {
|
||||
if (!g_cancellable_is_cancelled (data->cancellable)) {
|
||||
clapper_harvest_set_enhancer_in_caps (harvest, proxy);
|
||||
if (!g_cancellable_is_cancelled (data->cancellable))
|
||||
clapper_harvest_export_to_cache (harvest, proxy, config, data->uri);
|
||||
}
|
||||
|
||||
gst_clear_structure (&config);
|
||||
break;
|
||||
}
|
||||
@@ -164,8 +163,7 @@ clapper_enhancer_director_parse_in_thread (ClapperEnhancerDirectorData *data)
|
||||
|
||||
mem = gst_buffer_peek_memory (data->buffer, 0);
|
||||
if (!mem || !gst_memory_map (mem, &info, GST_MAP_READ)) {
|
||||
g_set_error (data->error, GST_RESOURCE_ERROR,
|
||||
GST_RESOURCE_ERROR_FAILED, "Could not read playlist buffer data");
|
||||
GST_ERROR_OBJECT (self, "Could not read playlist buffer data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -25,9 +25,7 @@
|
||||
#include "../clapper-media-item.h"
|
||||
#include "../clapper-playlistable.h"
|
||||
|
||||
#define CLAPPER_PLAYLIST_MEDIA_TYPE "application/clapper-playlist"
|
||||
#define CLAPPER_CLAPS_MEDIA_TYPE "text/clapper-claps"
|
||||
#define URI_LIST_MEDIA_TYPE "text/uri-list"
|
||||
#define CLAPPER_PLAYLIST_MEDIA_TYPE "text/clapper-playlist"
|
||||
#define DATA_CHUNK_SIZE 4096
|
||||
|
||||
#define GST_CAT_DEFAULT clapper_playlist_demux_debug
|
||||
@@ -55,32 +53,30 @@ static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (CLAPPER_PLAYLIST_MEDIA_TYPE ";" CLAPPER_CLAPS_MEDIA_TYPE ";" URI_LIST_MEDIA_TYPE));
|
||||
GST_STATIC_CAPS (CLAPPER_PLAYLIST_MEDIA_TYPE));
|
||||
|
||||
static GstStaticCaps clapper_playlist_caps = GST_STATIC_CAPS (CLAPPER_PLAYLIST_MEDIA_TYPE);
|
||||
static GstStaticCaps clapper_claps_caps = GST_STATIC_CAPS (CLAPPER_CLAPS_MEDIA_TYPE);
|
||||
static GstStaticCaps type_find_caps = GST_STATIC_CAPS (CLAPPER_PLAYLIST_MEDIA_TYPE);
|
||||
|
||||
static void
|
||||
clapper_playlist_type_find (GstTypeFind *tf, ClapperEnhancerProxy *proxy)
|
||||
{
|
||||
const gchar *prefix, *contains, *regex, *module_name;
|
||||
|
||||
if (!clapper_enhancer_proxy_get_target_creation_allowed (proxy))
|
||||
return;
|
||||
const gchar *prefix, *contains, *regex, *data;
|
||||
guint prob = 0;
|
||||
|
||||
if ((prefix = clapper_enhancer_proxy_get_extra_data (proxy, "X-Data-Prefix"))) {
|
||||
size_t len = strlen (prefix);
|
||||
const gchar *data = (const gchar *) gst_type_find_peek (tf, 0, (guint) len);
|
||||
data = (const gchar *) gst_type_find_peek (tf, 0, (guint) len);
|
||||
|
||||
if (!data || memcmp (data, prefix, len) != 0)
|
||||
return;
|
||||
|
||||
prob += 40;
|
||||
}
|
||||
|
||||
contains = clapper_enhancer_proxy_get_extra_data (proxy, "X-Data-Contains");
|
||||
regex = clapper_enhancer_proxy_get_extra_data (proxy, "X-Data-Regex");
|
||||
|
||||
if (contains || regex) {
|
||||
const gchar *data;
|
||||
guint data_size = DATA_CHUNK_SIZE;
|
||||
|
||||
if (!(data = (const gchar *) gst_type_find_peek (tf, 0, data_size))) {
|
||||
@@ -97,9 +93,12 @@ clapper_playlist_type_find (GstTypeFind *tf, ClapperEnhancerProxy *proxy)
|
||||
return;
|
||||
}
|
||||
|
||||
if (contains && !g_strstr_len (data, data_size, contains))
|
||||
return;
|
||||
if (contains) {
|
||||
if (!g_strstr_len (data, data_size, contains))
|
||||
return;
|
||||
|
||||
prob += 50;
|
||||
}
|
||||
if (regex) {
|
||||
GRegex *reg;
|
||||
GError *error = NULL;
|
||||
@@ -117,45 +116,21 @@ clapper_playlist_type_find (GstTypeFind *tf, ClapperEnhancerProxy *proxy)
|
||||
|
||||
if (!matched)
|
||||
return;
|
||||
|
||||
prob += 50;
|
||||
}
|
||||
}
|
||||
|
||||
module_name = clapper_enhancer_proxy_get_module_name (proxy);
|
||||
GST_INFO ("Suggesting likely type: " CLAPPER_PLAYLIST_MEDIA_TYPE
|
||||
", enhancer: %s", module_name);
|
||||
if (prob > 0) {
|
||||
const gchar *module_name = clapper_enhancer_proxy_get_module_name (proxy);
|
||||
|
||||
gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY,
|
||||
CLAPPER_PLAYLIST_MEDIA_TYPE, "enhancer", G_TYPE_STRING, module_name, NULL);
|
||||
}
|
||||
if (prob > 100)
|
||||
prob = 100;
|
||||
|
||||
/* Finds text file of full file paths. Claps file might also use URIs,
|
||||
* but in that case lets GStreamer built-in type finders find that as
|
||||
* "text/uri-list" and we will handle it with this element too. */
|
||||
static void
|
||||
clapper_claps_type_find (GstTypeFind *tf, gpointer user_data G_GNUC_UNUSED)
|
||||
{
|
||||
const guint8 *data;
|
||||
GST_INFO ("Type find prob of %s: %u%%", module_name, prob);
|
||||
|
||||
if ((data = gst_type_find_peek (tf, 0, 3))) {
|
||||
gboolean possible;
|
||||
|
||||
/* Linux file path */
|
||||
possible = (data[0] == '/' && g_ascii_isalnum (data[1]));
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* Windows file path ("C:\..." or "D:/...") */
|
||||
if (!possible)
|
||||
possible = (g_ascii_isalpha (data[0]) && data[1] == ':' && (data[2] == '\\' || data[2] == '/'));
|
||||
|
||||
/* Windows UNC Path */
|
||||
if (!possible)
|
||||
possible = (data[0] == '\\' && data[1] == '\\' && g_ascii_isalnum (data[2]));
|
||||
#endif
|
||||
|
||||
if (possible) {
|
||||
GST_INFO ("Suggesting possible type: " CLAPPER_CLAPS_MEDIA_TYPE);
|
||||
gst_type_find_suggest_empty_simple (tf, GST_TYPE_FIND_POSSIBLE, CLAPPER_CLAPS_MEDIA_TYPE);
|
||||
}
|
||||
gst_type_find_suggest_simple (tf, prob, CLAPPER_PLAYLIST_MEDIA_TYPE,
|
||||
"enhancer", G_TYPE_STRING, module_name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,25 +138,16 @@ static gboolean
|
||||
type_find_register (GstPlugin *plugin)
|
||||
{
|
||||
ClapperEnhancerProxyList *global_proxies = clapper_get_global_enhancer_proxies ();
|
||||
GstCaps *reg_caps;
|
||||
GstCaps *reg_caps = NULL;
|
||||
guint i, n_proxies = clapper_enhancer_proxy_list_get_n_proxies (global_proxies);
|
||||
gboolean res;
|
||||
|
||||
reg_caps = gst_static_caps_get (&clapper_claps_caps);
|
||||
res = gst_type_find_register (plugin, "clapper-claps",
|
||||
GST_RANK_MARGINAL + 1, (GstTypeFindFunction) clapper_claps_type_find,
|
||||
"claps", reg_caps, NULL, NULL);
|
||||
gst_clear_caps (®_caps);
|
||||
gboolean res = FALSE;
|
||||
|
||||
for (i = 0; i < n_proxies; ++i) {
|
||||
ClapperEnhancerProxy *proxy = clapper_enhancer_proxy_list_peek_proxy (global_proxies, i);
|
||||
|
||||
if (clapper_enhancer_proxy_target_has_interface (proxy, CLAPPER_TYPE_PLAYLISTABLE)
|
||||
&& (clapper_enhancer_proxy_get_extra_data (proxy, "X-Data-Prefix")
|
||||
|| clapper_enhancer_proxy_get_extra_data (proxy, "X-Data-Contains")
|
||||
|| clapper_enhancer_proxy_get_extra_data (proxy, "X-Data-Regex"))) {
|
||||
if (clapper_enhancer_proxy_target_has_interface (proxy, CLAPPER_TYPE_PLAYLISTABLE)) {
|
||||
if (!reg_caps)
|
||||
reg_caps = gst_static_caps_get (&clapper_playlist_caps);
|
||||
reg_caps = gst_static_caps_get (&type_find_caps);
|
||||
|
||||
res |= gst_type_find_register (plugin, clapper_enhancer_proxy_get_module_name (proxy),
|
||||
GST_RANK_MARGINAL + 1, (GstTypeFindFunction) clapper_playlist_type_find,
|
||||
@@ -200,86 +166,6 @@ GST_TYPE_FIND_REGISTER_DEFINE_CUSTOM (clapperplaylistdemux, type_find_register);
|
||||
GST_ELEMENT_REGISTER_DEFINE (clapperplaylistdemux, "clapperplaylistdemux",
|
||||
512, CLAPPER_TYPE_PLAYLIST_DEMUX);
|
||||
|
||||
static GListStore *
|
||||
_parse_uri_list (ClapperPlaylistDemux *self, GUri *uri, GstBuffer *buffer,
|
||||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
GListStore *playlist;
|
||||
GstMemory *mem;
|
||||
GstMapInfo info;
|
||||
const gchar *ptr, *end;
|
||||
|
||||
mem = gst_buffer_peek_memory (buffer, 0);
|
||||
if (!mem || !gst_memory_map (mem, &info, GST_MAP_READ)) {
|
||||
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
|
||||
"Could not read URI list buffer data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
playlist = g_list_store_new (CLAPPER_TYPE_MEDIA_ITEM);
|
||||
ptr = (gchar *) info.data;
|
||||
end = ptr + info.size;
|
||||
|
||||
while (ptr < end) {
|
||||
ClapperMediaItem *item = NULL;
|
||||
const gchar *nl = memchr (ptr, '\n', end - ptr);
|
||||
gsize len = nl ? nl - ptr : end - ptr;
|
||||
gchar *line;
|
||||
|
||||
if (g_cancellable_is_cancelled (cancellable))
|
||||
break;
|
||||
|
||||
line = g_strndup (ptr, len);
|
||||
GST_DEBUG_OBJECT (self, "Parsing line: %s", line);
|
||||
|
||||
if (gst_uri_is_valid (line)) {
|
||||
GST_DEBUG_OBJECT (self, "Found URI: %s", line);
|
||||
item = clapper_media_item_new (line);
|
||||
} else {
|
||||
gchar *base_uri, *res_uri;
|
||||
|
||||
base_uri = g_uri_to_string (uri);
|
||||
res_uri = g_uri_resolve_relative (base_uri, line, G_URI_FLAGS_ENCODED, error);
|
||||
g_free (base_uri);
|
||||
|
||||
if (res_uri) {
|
||||
GST_DEBUG_OBJECT (self, "Resolved URI: %s", res_uri);
|
||||
item = clapper_media_item_new (res_uri);
|
||||
g_free (res_uri);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (line);
|
||||
|
||||
if (G_UNLIKELY (*error != NULL)) {
|
||||
g_clear_object (&playlist);
|
||||
break;
|
||||
}
|
||||
|
||||
if (G_LIKELY (item != NULL))
|
||||
g_list_store_append (playlist, (GObject *) item);
|
||||
|
||||
/* Advance to the next line */
|
||||
ptr = nl ? (nl + 1) : end;
|
||||
}
|
||||
|
||||
gst_memory_unmap (mem, &info);
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_caps_have_media_type (GstCaps *caps, const gchar *media_type)
|
||||
{
|
||||
GstStructure *structure;
|
||||
gboolean is_media_type = FALSE;
|
||||
|
||||
if (caps && (structure = gst_caps_get_structure (caps, 0)))
|
||||
is_media_type = gst_structure_has_name (structure, media_type);
|
||||
|
||||
return is_media_type;
|
||||
}
|
||||
|
||||
static void
|
||||
clapper_playlist_demux_handle_caps (ClapperUriBaseDemux *uri_bd, GstCaps *caps)
|
||||
{
|
||||
@@ -315,7 +201,7 @@ _handle_playlist (ClapperPlaylistDemux *self, GListStore *playlist, GCancellable
|
||||
|
||||
if (G_UNLIKELY (item == NULL)) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
||||
("This playlist appears to be empty"), (NULL));
|
||||
("%s", "This playlist appears to be empty"), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -325,7 +211,7 @@ _handle_playlist (ClapperPlaylistDemux *self, GListStore *playlist, GCancellable
|
||||
|
||||
if (G_UNLIKELY (!success)) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
||||
("Resolved item URI was rejected"), (NULL));
|
||||
("%s", "Resolved item URI was rejected"), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -337,7 +223,7 @@ _handle_playlist (ClapperPlaylistDemux *self, GListStore *playlist, GCancellable
|
||||
gst_message_new_element (GST_OBJECT_CAST (self), structure));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -345,17 +231,15 @@ clapper_playlist_demux_process_buffer (ClapperUriBaseDemux *uri_bd,
|
||||
GstBuffer *buffer, GCancellable *cancellable)
|
||||
{
|
||||
ClapperPlaylistDemux *self = CLAPPER_PLAYLIST_DEMUX_CAST (uri_bd);
|
||||
GstPad *sink_pad;
|
||||
GstQuery *query;
|
||||
ClapperEnhancerProxyList *proxies;
|
||||
GList *filtered_proxies;
|
||||
GstCaps *caps = NULL;
|
||||
GstQuery *query = gst_query_new_uri ();
|
||||
GUri *uri = NULL;
|
||||
GListStore *playlist;
|
||||
GError *error = NULL;
|
||||
gboolean handled;
|
||||
|
||||
sink_pad = gst_element_get_static_pad (GST_ELEMENT_CAST (self), "sink");
|
||||
query = gst_query_new_uri ();
|
||||
|
||||
if (gst_pad_peer_query (sink_pad, query)) {
|
||||
if (gst_pad_peer_query (GST_ELEMENT_CAST (self)->sinkpads->data, query)) {
|
||||
gchar *query_uri;
|
||||
|
||||
gst_query_parse_uri (query, &query_uri);
|
||||
@@ -366,52 +250,39 @@ clapper_playlist_demux_process_buffer (ClapperUriBaseDemux *uri_bd,
|
||||
g_free (query_uri);
|
||||
}
|
||||
}
|
||||
|
||||
gst_query_unref (query);
|
||||
gst_object_unref (sink_pad);
|
||||
|
||||
if (G_UNLIKELY (uri == NULL)) {
|
||||
GST_ERROR_OBJECT (self, "Could not query source URI");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_caps_have_media_type (self->caps, CLAPPER_PLAYLIST_MEDIA_TYPE)) {
|
||||
ClapperEnhancerProxyList *proxies;
|
||||
GList *filtered_proxies;
|
||||
if (!self->director)
|
||||
self->director = clapper_enhancer_director_new ();
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
if (G_LIKELY (self->enhancer_proxies != NULL)) {
|
||||
GST_INFO_OBJECT (self, "Using enhancer proxies: %" GST_PTR_FORMAT, self->enhancer_proxies);
|
||||
proxies = gst_object_ref (self->enhancer_proxies);
|
||||
} else {
|
||||
/* Compat for old ClapperDiscoverer feature that does not set this property */
|
||||
GST_WARNING_OBJECT (self, "Falling back to using global enhancer proxy list!");
|
||||
proxies = gst_object_ref (clapper_get_global_enhancer_proxies ());
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
if (!self->director)
|
||||
self->director = clapper_enhancer_director_new ();
|
||||
|
||||
filtered_proxies = _filter_playlistables (self, self->caps, proxies);
|
||||
gst_object_unref (proxies);
|
||||
|
||||
playlist = clapper_enhancer_director_parse (self->director,
|
||||
filtered_proxies, uri, buffer, cancellable, &error);
|
||||
|
||||
g_clear_list (&filtered_proxies, gst_object_unref);
|
||||
} else if (_caps_have_media_type (self->caps, URI_LIST_MEDIA_TYPE)
|
||||
|| _caps_have_media_type (self->caps, CLAPPER_CLAPS_MEDIA_TYPE)) {
|
||||
playlist = _parse_uri_list (self, uri, buffer, cancellable, &error);
|
||||
} else { // Should never happen
|
||||
playlist = NULL;
|
||||
error = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
|
||||
"Unsupported media type in caps");
|
||||
if (G_LIKELY (self->enhancer_proxies != NULL)) {
|
||||
GST_INFO_OBJECT (self, "Using enhancer proxies: %" GST_PTR_FORMAT, self->enhancer_proxies);
|
||||
proxies = gst_object_ref (self->enhancer_proxies);
|
||||
} else {
|
||||
/* Compat for old ClapperDiscoverer feature that does not set this property */
|
||||
GST_WARNING_OBJECT (self, "Falling back to using global enhancer proxy list!");
|
||||
proxies = gst_object_ref (clapper_get_global_enhancer_proxies ());
|
||||
}
|
||||
|
||||
g_uri_unref (uri);
|
||||
gst_caps_replace (&caps, self->caps);
|
||||
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
filtered_proxies = _filter_playlistables (self, caps, proxies);
|
||||
gst_clear_caps (&caps);
|
||||
gst_object_unref (proxies);
|
||||
|
||||
playlist = clapper_enhancer_director_parse (self->director,
|
||||
filtered_proxies, uri, buffer, cancellable, &error);
|
||||
|
||||
g_clear_list (&filtered_proxies, gst_object_unref);
|
||||
|
||||
if (!playlist) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
||||
@@ -421,10 +292,7 @@ clapper_playlist_demux_process_buffer (ClapperUriBaseDemux *uri_bd,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
handled = _handle_playlist (self, playlist, cancellable);
|
||||
g_object_unref (playlist);
|
||||
|
||||
return handled;
|
||||
return _handle_playlist (self, playlist, cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Reference in New Issue
Block a user