Compare commits

..

8 Commits

Author SHA1 Message Date
Rafał Dzięgiel
b4922a5847 clapper: discoverer: Skip items that already have tags
When tags are populated elsewhere, do not run discovery on them again.
It is possible they were discovered in more efficient maner
(e.g. from playlist data itself).

This avoid us downloading each media item separately after all
playlist items are queued.
2025-07-25 20:45:49 +02:00
Rafał Dzięgiel
554548fbe0 clapper-app: Remove claps handling code
It is now handled inside playlist demuxer, with the other playlist formats
2025-07-25 20:45:46 +02:00
Rafał Dzięgiel
e158fe9b5b clapper: Support demuxing uri-list and claps files 2025-07-25 20:45:44 +02:00
Rafał Dzięgiel
c5da836bf1 clapper: Update harvest common formats description 2025-07-25 20:45:41 +02:00
Rafał Dzięgiel
aacf798c49 clapper: Store full caps in harvest
Make it possible to know which enhancer harvested this cached data
2025-07-25 20:45:36 +02:00
Rafał Dzięgiel
b717471d91 clapper: Rename "uri-list-demux" element
Move as harvest URI demuxer since it is supposed to work only with
harvest data from extractable src. Also change caps media type
to "text/x-uri" which is non-standard, but we have to differentiate
single URI from harvest and URI list (one or more URIs).
2025-07-25 20:45:33 +02:00
Rafał Dzięgiel
ea4a7d3761 clapper: Handle parsed playlists
Handle "ClapperPlaylistParsed" messages on playbin bus by updating current media
item (playlist) to redirect to the first item in that playlist (with changed tags)
and appending remaining items to the queue after that playlist position.

This basically means that playlist gets resolved into simply adding more
items to the queue. This should also work with nested playlists within playlist.
2025-07-25 20:45:22 +02:00
Rafał Dzięgiel
7821b5bc20 clapper: Add playlist demuxer element
Uses "Playlistable" enhancers to parse playlist and demux first URI in it
2025-07-19 15:43:38 +02:00
2 changed files with 32 additions and 35 deletions

View File

@@ -131,7 +131,7 @@ _run_discovery (ClapperDiscoverer *self)
ClapperDiscovererDiscoveryMode discovery_mode;
GstTagList *tags;
const gchar *uri;
gboolean empty_tags, success = FALSE;
gboolean had_tags, success = FALSE;
if (self->pending_items->len == 0) {
GST_DEBUG_OBJECT (self, "No more pending items");
@@ -160,10 +160,10 @@ _run_discovery (ClapperDiscoverer *self)
}
tags = clapper_media_item_get_tags (item);
empty_tags = gst_tag_list_is_empty (tags);
had_tags = !gst_tag_list_is_empty (tags);
gst_tag_list_unref (tags);
if (!empty_tags) {
if (had_tags) {
GST_DEBUG_OBJECT (self, "Queued %" GST_PTR_FORMAT
" already has tags, ignoring discovery", item);
goto finish;

View File

@@ -63,24 +63,23 @@ static GstStaticCaps clapper_claps_caps = GST_STATIC_CAPS (CLAPPER_CLAPS_MEDIA_T
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 +96,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,15 +119,22 @@ 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;
GST_INFO ("Type find prob of %s: %u%%", module_name, prob);
gst_type_find_suggest_simple (tf, prob, CLAPPER_PLAYLIST_MEDIA_TYPE,
"enhancer", G_TYPE_STRING, module_name, NULL);
}
}
/* Finds text file of full file paths. Claps file might also use URIs,
@@ -257,7 +266,7 @@ _parse_uri_list (ClapperPlaylistDemux *self, GUri *uri, GstBuffer *buffer,
}
if (G_LIKELY (item != NULL))
g_list_store_append (playlist, (GObject *) item);
g_list_store_append (playlist, G_OBJECT (item));
/* Advance to the next line */
ptr = nl ? (nl + 1) : end;
@@ -315,7 +324,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 +334,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 +346,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 +354,12 @@ 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;
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,9 +370,7 @@ 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");
@@ -411,8 +413,6 @@ clapper_playlist_demux_process_buffer (ClapperUriBaseDemux *uri_bd,
"Unsupported media type in caps");
}
g_uri_unref (uri);
if (!playlist) {
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
("%s", error->message), (NULL));
@@ -421,10 +421,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