mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
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.
This commit is contained in:
@@ -44,6 +44,8 @@ void clapper_app_bus_post_refresh_streams (ClapperAppBus *app_bus, GstObject *sr
|
||||
|
||||
void clapper_app_bus_post_refresh_timeline (ClapperAppBus *app_bus, GstObject *src);
|
||||
|
||||
void clapper_app_bus_post_insert_playlist (ClapperAppBus *app_bus, GstObject *src, GstObject *playlist_item, GObject *playlist);
|
||||
|
||||
void clapper_app_bus_post_simple_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id);
|
||||
|
||||
void clapper_app_bus_post_object_desc_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GstObject *object, const gchar *desc);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "clapper-bus-private.h"
|
||||
#include "clapper-app-bus-private.h"
|
||||
#include "clapper-player-private.h"
|
||||
#include "clapper-queue-private.h"
|
||||
#include "clapper-media-item-private.h"
|
||||
#include "clapper-timeline-private.h"
|
||||
|
||||
@@ -41,6 +42,7 @@ enum
|
||||
CLAPPER_APP_BUS_STRUCTURE_PROP_NOTIFY,
|
||||
CLAPPER_APP_BUS_STRUCTURE_REFRESH_STREAMS,
|
||||
CLAPPER_APP_BUS_STRUCTURE_REFRESH_TIMELINE,
|
||||
CLAPPER_APP_BUS_STRUCTURE_INSERT_PLAYLIST,
|
||||
CLAPPER_APP_BUS_STRUCTURE_SIMPLE_SIGNAL,
|
||||
CLAPPER_APP_BUS_STRUCTURE_OBJECT_DESC_SIGNAL,
|
||||
CLAPPER_APP_BUS_STRUCTURE_DESC_WITH_DETAILS_SIGNAL,
|
||||
@@ -52,6 +54,7 @@ static ClapperBusQuark _structure_quarks[] = {
|
||||
{"prop-notify", 0},
|
||||
{"refresh-streams", 0},
|
||||
{"refresh-timeline", 0},
|
||||
{"insert-playlist", 0},
|
||||
{"simple-signal", 0},
|
||||
{"object-desc-signal", 0},
|
||||
{"desc-with-details-signal", 0},
|
||||
@@ -65,6 +68,7 @@ enum
|
||||
CLAPPER_APP_BUS_FIELD_PSPEC,
|
||||
CLAPPER_APP_BUS_FIELD_SIGNAL_ID,
|
||||
CLAPPER_APP_BUS_FIELD_OBJECT,
|
||||
CLAPPER_APP_BUS_FIELD_OTHER_OBJECT,
|
||||
CLAPPER_APP_BUS_FIELD_DESC,
|
||||
CLAPPER_APP_BUS_FIELD_DETAILS,
|
||||
CLAPPER_APP_BUS_FIELD_ERROR,
|
||||
@@ -76,6 +80,7 @@ static ClapperBusQuark _field_quarks[] = {
|
||||
{"pspec", 0},
|
||||
{"signal-id", 0},
|
||||
{"object", 0},
|
||||
{"other-object", 0},
|
||||
{"desc", 0},
|
||||
{"details", 0},
|
||||
{"error", 0},
|
||||
@@ -160,6 +165,36 @@ _handle_refresh_timeline_msg (GstMessage *msg, const GstStructure *structure)
|
||||
clapper_timeline_refresh (timeline);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_app_bus_post_insert_playlist (ClapperAppBus *self, GstObject *src,
|
||||
GstObject *playlist_item, GObject *playlist)
|
||||
{
|
||||
GstStructure *structure = gst_structure_new_id (_STRUCTURE_QUARK (INSERT_PLAYLIST),
|
||||
_FIELD_QUARK (OBJECT), GST_TYPE_OBJECT, playlist_item,
|
||||
_FIELD_QUARK (OTHER_OBJECT), G_TYPE_OBJECT, playlist,
|
||||
NULL);
|
||||
gst_bus_post (GST_BUS_CAST (self), gst_message_new_application (src, structure));
|
||||
}
|
||||
|
||||
static inline void
|
||||
_handle_insert_playlist_msg (GstMessage *msg, const GstStructure *structure)
|
||||
{
|
||||
ClapperPlayer *player = CLAPPER_PLAYER_CAST (GST_MESSAGE_SRC (msg));
|
||||
ClapperQueue *queue = clapper_player_get_queue (player);
|
||||
GstObject *playlist_item;
|
||||
GObject *playlist;
|
||||
|
||||
gst_structure_id_get (structure,
|
||||
_FIELD_QUARK (OBJECT), GST_TYPE_OBJECT, &playlist_item,
|
||||
_FIELD_QUARK (OTHER_OBJECT), G_TYPE_OBJECT, &playlist,
|
||||
NULL);
|
||||
clapper_queue_handle_playlist (queue,
|
||||
CLAPPER_MEDIA_ITEM (playlist_item), G_LIST_STORE (playlist));
|
||||
|
||||
gst_object_unref (playlist_item);
|
||||
g_object_unref (playlist);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_app_bus_post_simple_signal (ClapperAppBus *self, GstObject *src, guint signal_id)
|
||||
{
|
||||
@@ -285,6 +320,8 @@ clapper_app_bus_message_func (GstBus *bus, GstMessage *msg, gpointer user_data G
|
||||
_handle_refresh_streams_msg (msg, structure);
|
||||
else if (quark == _STRUCTURE_QUARK (REFRESH_TIMELINE))
|
||||
_handle_refresh_timeline_msg (msg, structure);
|
||||
else if (quark == _STRUCTURE_QUARK (INSERT_PLAYLIST))
|
||||
_handle_insert_playlist_msg (msg, structure);
|
||||
else if (quark == _STRUCTURE_QUARK (SIMPLE_SIGNAL))
|
||||
_handle_simple_signal_msg (msg, structure);
|
||||
else if (quark == _STRUCTURE_QUARK (OBJECT_DESC_SIGNAL))
|
||||
|
@@ -33,6 +33,9 @@ void clapper_media_item_update_from_tag_list (ClapperMediaItem *item, const GstT
|
||||
G_GNUC_INTERNAL
|
||||
void clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDiscovererInfo *info);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean clapper_media_item_update_from_item (ClapperMediaItem *item, ClapperMediaItem *other_item, ClapperPlayer *player);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean clapper_media_item_set_duration (ClapperMediaItem *item, gdouble duration, ClapperAppBus *app_bus);
|
||||
|
||||
|
@@ -51,6 +51,10 @@ struct _ClapperMediaItem
|
||||
gchar *container_format;
|
||||
gdouble duration;
|
||||
|
||||
/* Whether using title from URI */
|
||||
gboolean title_is_parsed;
|
||||
|
||||
GSList *redirects;
|
||||
gchar *cache_uri;
|
||||
|
||||
/* For shuffle */
|
||||
@@ -198,6 +202,12 @@ 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
|
||||
@@ -295,11 +305,11 @@ clapper_media_item_get_title (ClapperMediaItem *self)
|
||||
|
||||
static inline gboolean
|
||||
_refresh_tag_prop_unlocked (ClapperMediaItem *self, const gchar *tag,
|
||||
gboolean from_user, gchar **tag_ptr)
|
||||
gboolean allow_overwrite, gchar **tag_ptr)
|
||||
{
|
||||
const gchar *string;
|
||||
|
||||
if ((*tag_ptr && from_user) // if already set, user cannot modify it
|
||||
if ((*tag_ptr && !allow_overwrite)
|
||||
|| !gst_tag_list_peek_string_index (self->tags, tag, 0, &string) // guarantees non-empty string
|
||||
|| (g_strcmp0 (*tag_ptr, string) == 0))
|
||||
return FALSE;
|
||||
@@ -488,11 +498,12 @@ clapper_media_item_insert_tags_internal (ClapperMediaItem *self, const GstTagLis
|
||||
*flags |= CLAPPER_REACTABLE_ITEM_UPDATED_TAGS;
|
||||
|
||||
if ((title_changed = _refresh_tag_prop_unlocked (self, GST_TAG_TITLE,
|
||||
from_user, &self->title))) {
|
||||
(!from_user || self->title_is_parsed), &self->title))) {
|
||||
self->title_is_parsed = FALSE;
|
||||
*flags |= CLAPPER_REACTABLE_ITEM_UPDATED_TITLE;
|
||||
}
|
||||
cont_changed = _refresh_tag_prop_unlocked (self, GST_TAG_CONTAINER_FORMAT,
|
||||
from_user, &self->container_format);
|
||||
!from_user, &self->container_format);
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
@@ -668,6 +679,61 @@ clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDisco
|
||||
gst_object_unref (player);
|
||||
}
|
||||
|
||||
/* XXX: Must be set from player thread */
|
||||
static inline gboolean
|
||||
clapper_media_item_set_redirect_uri (ClapperMediaItem *self, const gchar *redirect_uri)
|
||||
{
|
||||
/* Check if we did not already redirect into that URI (prevent endless loop) */
|
||||
if (!redirect_uri || g_slist_find_custom (self->redirects, redirect_uri, (GCompareFunc) strcmp))
|
||||
return FALSE;
|
||||
|
||||
self->redirects = g_slist_prepend (self->redirects, g_strdup (redirect_uri));
|
||||
GST_DEBUG_OBJECT (self, "Set redirect URI: \"%s\"", (gchar *) self->redirects->data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
GST_OBJECT_LOCK (other_item);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* XXX: Must be set from player thread or upon construction */
|
||||
void
|
||||
clapper_media_item_set_cache_location (ClapperMediaItem *self, const gchar *location)
|
||||
@@ -682,7 +748,7 @@ clapper_media_item_set_cache_location (ClapperMediaItem *self, const gchar *loca
|
||||
}
|
||||
|
||||
/* XXX: Can only be read from player thread.
|
||||
* Returns cache URI if available, item URI otherwise. */
|
||||
* Returns cache URI if available, otherwise redirect or item URI. */
|
||||
inline const gchar *
|
||||
clapper_media_item_get_playback_uri (ClapperMediaItem *self)
|
||||
{
|
||||
@@ -702,6 +768,9 @@ clapper_media_item_get_playback_uri (ClapperMediaItem *self)
|
||||
clapper_media_item_set_cache_location (self, NULL);
|
||||
}
|
||||
|
||||
if (self->redirects)
|
||||
return self->redirects->data;
|
||||
|
||||
return self->uri;
|
||||
}
|
||||
|
||||
@@ -745,6 +814,7 @@ clapper_media_item_constructed (GObject *object)
|
||||
self->uri = g_strdup ("file://");
|
||||
|
||||
self->title = clapper_utils_title_from_uri (self->uri);
|
||||
self->title_is_parsed = (self->title != NULL);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
}
|
||||
@@ -765,6 +835,7 @@ clapper_media_item_finalize (GObject *object)
|
||||
gst_object_unparent (GST_OBJECT_CAST (self->timeline));
|
||||
gst_object_unref (self->timeline);
|
||||
|
||||
g_slist_free_full (self->redirects, g_free);
|
||||
g_free (self->cache_uri);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
@@ -892,7 +963,8 @@ clapper_media_item_class_init (ClapperMediaItemClass *klass)
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/* FIXME: 1.0: Consider rename to e.g. "(menu/display)-title"
|
||||
* and also make it non-nullable (return URI as final fallback) */
|
||||
* and also make it non-nullable (return URI as final fallback).
|
||||
* NOTE: It would probably need to work with redirect URI */
|
||||
/**
|
||||
* ClapperMediaItem:title:
|
||||
*
|
||||
|
@@ -831,6 +831,71 @@ _handle_element_msg (GstMessage *msg, ClapperPlayer *player)
|
||||
|
||||
g_free (name);
|
||||
g_free (details);
|
||||
} else if (gst_message_has_name (msg, "ClapperPlaylistParsed")) {
|
||||
ClapperMediaItem *playlist_item = NULL;
|
||||
GListStore *playlist = NULL;
|
||||
const GstStructure *structure = gst_message_get_structure (msg);
|
||||
guint n_items;
|
||||
|
||||
/* If message contains item, use that.
|
||||
* Otherwise assume pending item was parsed. */
|
||||
if (gst_structure_has_field (structure, "item")) {
|
||||
gst_structure_get (structure,
|
||||
"item", CLAPPER_TYPE_MEDIA_ITEM, &playlist_item, NULL);
|
||||
} else {
|
||||
GST_OBJECT_LOCK (player);
|
||||
|
||||
/* Playlist is always parsed before playback starts */
|
||||
if (player->pending_item)
|
||||
playlist_item = gst_object_ref (player->pending_item);
|
||||
|
||||
GST_OBJECT_UNLOCK (player);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (playlist_item == NULL)) {
|
||||
GST_WARNING_OBJECT (player, "Playlist parsed without media item set");
|
||||
return;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (player, "Received parsed playlist of %" GST_PTR_FORMAT
|
||||
"(%s)", playlist_item, clapper_media_item_get_uri (playlist_item));
|
||||
|
||||
gst_structure_get (structure,
|
||||
"playlist", G_TYPE_LIST_STORE, &playlist, NULL);
|
||||
|
||||
n_items = g_list_model_get_n_items (G_LIST_MODEL (playlist));
|
||||
|
||||
if (G_LIKELY (n_items > 0)) {
|
||||
ClapperMediaItem *active_item = g_list_model_get_item (G_LIST_MODEL (playlist), 0);
|
||||
gboolean updated;
|
||||
|
||||
/* Update redirect URI (must be done from player thread) */
|
||||
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) */
|
||||
clapper_app_bus_post_insert_playlist (player->app_bus,
|
||||
GST_OBJECT_CAST (player),
|
||||
GST_OBJECT_CAST (playlist_item),
|
||||
G_OBJECT (playlist));
|
||||
}
|
||||
}
|
||||
|
||||
gst_object_unref (playlist_item);
|
||||
g_object_unref (playlist);
|
||||
} else if (gst_message_has_name (msg, "GstCacheDownloadComplete")) {
|
||||
ClapperMediaItem *downloaded_item = NULL;
|
||||
const GstStructure *structure;
|
||||
|
@@ -826,7 +826,8 @@ _element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self
|
||||
factory_name = g_intern_static_string (GST_OBJECT_NAME (factory));
|
||||
GST_INFO_OBJECT (self, "Element setup: %s", factory_name);
|
||||
|
||||
if (factory_name == g_intern_static_string ("clapperextractablesrc")) {
|
||||
if (factory_name == g_intern_static_string ("clapperextractablesrc")
|
||||
|| factory_name == g_intern_static_string ("clapperplaylistdemux")) {
|
||||
g_object_set (element,
|
||||
"enhancer-proxies", self->enhancer_proxies,
|
||||
NULL);
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "clapper-queue.h"
|
||||
#include "clapper-media-item.h"
|
||||
@@ -31,6 +32,8 @@ ClapperQueue * clapper_queue_new (void);
|
||||
|
||||
void clapper_queue_handle_played_item_changed (ClapperQueue *queue, ClapperMediaItem *played_item, ClapperAppBus *app_bus);
|
||||
|
||||
void clapper_queue_handle_playlist (ClapperQueue *queue, ClapperMediaItem *playlist_item, GListStore *playlist);
|
||||
|
||||
void clapper_queue_handle_about_to_finish (ClapperQueue *queue, ClapperPlayer *player);
|
||||
|
||||
gboolean clapper_queue_handle_eos (ClapperQueue *queue, ClapperPlayer *player);
|
||||
|
@@ -337,6 +337,42 @@ _get_next_item_unlocked (ClapperQueue *self, ClapperQueueProgressionMode mode)
|
||||
return next_item;
|
||||
}
|
||||
|
||||
static void
|
||||
_take_item_unlocked (ClapperQueue *self, ClapperMediaItem *item, gint index)
|
||||
{
|
||||
guint prev_length = self->items->len;
|
||||
|
||||
g_ptr_array_insert (self->items, index, item);
|
||||
gst_object_set_parent (GST_OBJECT_CAST (item), GST_OBJECT_CAST (self));
|
||||
|
||||
/* In append we inserted at array length */
|
||||
if (index < 0)
|
||||
index = prev_length;
|
||||
|
||||
_announce_model_update (self, index, 0, 1, item);
|
||||
|
||||
/* If has selection and inserting before it */
|
||||
if (self->current_index != CLAPPER_QUEUE_INVALID_POSITION
|
||||
&& (guint) index <= self->current_index) {
|
||||
self->current_index++;
|
||||
_announce_current_index_change (self);
|
||||
} else if (prev_length == 0 && _replace_current_item_unlocked (self, item, 0)) {
|
||||
/* If queue was empty, auto select first item and announce it */
|
||||
_announce_current_item_and_index_change (self);
|
||||
} else if (self->current_index == prev_length - 1
|
||||
&& clapper_queue_get_progression_mode (self) == CLAPPER_QUEUE_PROGRESSION_CONSECUTIVE) {
|
||||
ClapperPlayer *player = clapper_player_get_from_ancestor (GST_OBJECT_CAST (self));
|
||||
gboolean after_eos = (gboolean) g_atomic_int_get (&player->eos);
|
||||
|
||||
/* In consecutive progression automatically select next item
|
||||
* if we were after EOS of last queue item */
|
||||
if (after_eos && _replace_current_item_unlocked (self, item, index))
|
||||
_announce_current_item_and_index_change (self);
|
||||
|
||||
gst_object_unref (player);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For gapless we need to manually replace current item in queue when it starts
|
||||
* playing and emit notify about change, this function will do that if necessary
|
||||
@@ -366,6 +402,31 @@ clapper_queue_handle_played_item_changed (ClapperQueue *self, ClapperMediaItem *
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be called from main thread */
|
||||
void
|
||||
clapper_queue_handle_playlist (ClapperQueue *self, ClapperMediaItem *playlist_item,
|
||||
GListStore *playlist)
|
||||
{
|
||||
GListModel *playlist_model = G_LIST_MODEL (playlist);
|
||||
guint i, index, n_items = g_list_model_get_n_items (playlist_model);
|
||||
|
||||
CLAPPER_QUEUE_REC_LOCK (self);
|
||||
|
||||
/* If playlist item is still in the queue, insert
|
||||
* remaining items after it, otherwise append */
|
||||
if (G_LIKELY (g_ptr_array_find (self->items, playlist_item, &index)))
|
||||
index++;
|
||||
else
|
||||
index = self->items->len;
|
||||
|
||||
for (i = 1; i < n_items; ++i) {
|
||||
ClapperMediaItem *item = g_list_model_get_item (playlist_model, i);
|
||||
_take_item_unlocked (self, item, index++);
|
||||
}
|
||||
|
||||
CLAPPER_QUEUE_REC_UNLOCK (self);
|
||||
}
|
||||
|
||||
void
|
||||
clapper_queue_handle_about_to_finish (ClapperQueue *self, ClapperPlayer *player)
|
||||
{
|
||||
@@ -481,39 +542,8 @@ clapper_queue_insert_item (ClapperQueue *self, ClapperMediaItem *item, gint inde
|
||||
|
||||
CLAPPER_QUEUE_REC_LOCK (self);
|
||||
|
||||
if (!g_ptr_array_find (self->items, item, NULL)) {
|
||||
guint prev_length = self->items->len;
|
||||
|
||||
g_ptr_array_insert (self->items, index, gst_object_ref (item));
|
||||
gst_object_set_parent (GST_OBJECT_CAST (item), GST_OBJECT_CAST (self));
|
||||
|
||||
/* In append we inserted at array length */
|
||||
if (index < 0)
|
||||
index = prev_length;
|
||||
|
||||
_announce_model_update (self, index, 0, 1, item);
|
||||
|
||||
/* If has selection and inserting before it */
|
||||
if (self->current_index != CLAPPER_QUEUE_INVALID_POSITION
|
||||
&& (guint) index <= self->current_index) {
|
||||
self->current_index++;
|
||||
_announce_current_index_change (self);
|
||||
} else if (prev_length == 0 && _replace_current_item_unlocked (self, item, 0)) {
|
||||
/* If queue was empty, auto select first item and announce it */
|
||||
_announce_current_item_and_index_change (self);
|
||||
} else if (self->current_index == prev_length - 1
|
||||
&& clapper_queue_get_progression_mode (self) == CLAPPER_QUEUE_PROGRESSION_CONSECUTIVE) {
|
||||
ClapperPlayer *player = clapper_player_get_from_ancestor (GST_OBJECT_CAST (self));
|
||||
gboolean after_eos = (gboolean) g_atomic_int_get (&player->eos);
|
||||
|
||||
/* In consecutive progression automatically select next item
|
||||
* if we were after EOS of last queue item */
|
||||
if (after_eos && _replace_current_item_unlocked (self, item, index))
|
||||
_announce_current_item_and_index_change (self);
|
||||
|
||||
gst_object_unref (player);
|
||||
}
|
||||
}
|
||||
if (!g_ptr_array_find (self->items, item, NULL))
|
||||
_take_item_unlocked (self, gst_object_ref (item), index);
|
||||
|
||||
CLAPPER_QUEUE_REC_UNLOCK (self);
|
||||
}
|
||||
|
Reference in New Issue
Block a user