mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 23:32:04 +02:00
clapper: Add "Reactable" interface
An interface for creating enhancers that react to the playback and/or events that should influence it.
This commit is contained in:
@@ -30,6 +30,8 @@
|
||||
* virtual functions logic, while for controlling playback implementation
|
||||
* may call [method@Gst.Object.get_parent] to acquire a weak reference on
|
||||
* a parent [class@Clapper.Player] object feature was added to.
|
||||
*
|
||||
* Deprecated: 0.10: Use [iface@Clapper.Reactable] instead.
|
||||
*/
|
||||
|
||||
#include "clapper-feature.h"
|
||||
|
@@ -37,7 +37,7 @@ G_BEGIN_DECLS
|
||||
#define CLAPPER_TYPE_FEATURE (clapper_feature_get_type())
|
||||
#define CLAPPER_FEATURE_CAST(obj) ((ClapperFeature *)(obj))
|
||||
|
||||
CLAPPER_API
|
||||
CLAPPER_DEPRECATED_FOR(ClapperReactable)
|
||||
G_DECLARE_DERIVABLE_TYPE (ClapperFeature, clapper_feature, CLAPPER, FEATURE, GstObject)
|
||||
|
||||
/**
|
||||
|
210
src/lib/clapper/clapper-reactable.c
Normal file
210
src/lib/clapper/clapper-reactable.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/* Clapper Playback Library
|
||||
* Copyright (C) 2025 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClapperReactable:
|
||||
*
|
||||
* An interface for creating enhancers that react to the
|
||||
* playback and/or events that should influence it.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
|
||||
#include "clapper-reactable.h"
|
||||
#include "clapper-utils-private.h"
|
||||
|
||||
#define CLAPPER_REACTABLE_DO_WITH_QUEUE(reactable, _queue_dst, ...) { \
|
||||
ClapperPlayer *_player = clapper_reactable_get_player (reactable); \
|
||||
if (G_LIKELY (_player != NULL)) { \
|
||||
*_queue_dst = clapper_player_get_queue (_player); \
|
||||
__VA_ARGS__ \
|
||||
gst_object_unref (_player); }}
|
||||
|
||||
G_DEFINE_INTERFACE (ClapperReactable, clapper_reactable, GST_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
clapper_reactable_default_init (ClapperReactableInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_reactable_get_player:
|
||||
* @reactable: a #ClapperReactable
|
||||
*
|
||||
* Get the [class@Clapper.Player] that this reactable is reacting to.
|
||||
*
|
||||
* This is meant to be used in implementations where reaction goes the
|
||||
* other way around (from enhancer plugin to the player). For example
|
||||
* some external event needs to influence parent player object like
|
||||
* changing its state, seeking, etc.
|
||||
*
|
||||
* Note that enhancers are working in a non-main application thread, thus
|
||||
* if you need to do operations on a [class@Clapper.Queue] such as adding/removing
|
||||
* items, you need to switch thread first. Otherwise this will not be thread safe
|
||||
* for applications that use single threaded toolkits such as #GTK. You can do this
|
||||
* manually or use provided reactable convenience functions.
|
||||
*
|
||||
* Due to the threaded nature, you should also avoid comparisons to the current
|
||||
* properties values in the player or its queue. While these are thread safe, there
|
||||
* is no guarantee that values/objects between threads are still the same in both
|
||||
* (or still exist). For example, instead of using [property@Clapper.Queue:current_item],
|
||||
* monitor it with implemented [vfunc@Clapper.Reactable.played_item_changed] instead,
|
||||
* as these functions are all serialized into your implementation thread.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): A reference to the parent #ClapperPlayer.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
ClapperPlayer *
|
||||
clapper_reactable_get_player (ClapperReactable *self)
|
||||
{
|
||||
g_return_val_if_fail (CLAPPER_IS_REACTABLE (self), NULL);
|
||||
|
||||
return CLAPPER_PLAYER_CAST (gst_object_get_parent (GST_OBJECT_CAST (self)));
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_reactable_queue_append_sync:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem
|
||||
*
|
||||
* A convenience function that within application main thread synchronously appends
|
||||
* an @item to the playback queue of the player that @reactable belongs to.
|
||||
*
|
||||
* Reactable enhancers should only modify the queue from the application
|
||||
* main thread, switching thread either themselves or using this convenience
|
||||
* function that does so.
|
||||
*
|
||||
* Note that this function will do no operation if called when there is no player
|
||||
* set yet (e.g. inside enhancer construction) or if enhancer outlived the parent
|
||||
* instance somehow. Both cases are considered to be implementation bug.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void
|
||||
clapper_reactable_queue_append_sync (ClapperReactable *self, ClapperMediaItem *item)
|
||||
{
|
||||
ClapperQueue *queue;
|
||||
|
||||
g_return_if_fail (CLAPPER_IS_REACTABLE (self));
|
||||
g_return_if_fail (CLAPPER_IS_MEDIA_ITEM (item));
|
||||
|
||||
CLAPPER_REACTABLE_DO_WITH_QUEUE (self, &queue, {
|
||||
clapper_utils_queue_append_on_main_sync (queue, item);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_reactable_queue_insert_sync:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem
|
||||
* @after_item: a #ClapperMediaItem after which to insert or %NULL to prepend
|
||||
*
|
||||
* A convenience function that within application main thread synchronously inserts
|
||||
* an @item to the playback queue position after @after_item of the player that
|
||||
* @reactable belongs to.
|
||||
*
|
||||
* This function uses @after_item instead of position index in order to ensure
|
||||
* desired position does not change during thread switching.
|
||||
*
|
||||
* Reactable enhancers should only modify the queue from the application
|
||||
* main thread, switching thread either themselves or using this convenience
|
||||
* function that does so.
|
||||
*
|
||||
* Note that this function will do no operation if called when there is no player
|
||||
* set yet (e.g. inside enhancer construction) or if enhancer outlived the parent
|
||||
* instance somehow. Both cases are considered to be implementation bug.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void
|
||||
clapper_reactable_queue_insert_sync (ClapperReactable *self,
|
||||
ClapperMediaItem *item, ClapperMediaItem *after_item)
|
||||
{
|
||||
ClapperQueue *queue;
|
||||
|
||||
g_return_if_fail (CLAPPER_IS_REACTABLE (self));
|
||||
g_return_if_fail (CLAPPER_IS_MEDIA_ITEM (item));
|
||||
g_return_if_fail (after_item == NULL || CLAPPER_IS_MEDIA_ITEM (after_item));
|
||||
|
||||
CLAPPER_REACTABLE_DO_WITH_QUEUE (self, &queue, {
|
||||
clapper_utils_queue_insert_on_main_sync (queue, item, after_item);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_reactable_queue_remove_sync:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem
|
||||
*
|
||||
* A convenience function that within application main thread synchronously removes
|
||||
* an @item from the playback queue of the player that @reactable belongs to.
|
||||
*
|
||||
* Reactable enhancers should only modify the queue from the application
|
||||
* main thread, switching thread either themselves or using this convenience
|
||||
* function that does so.
|
||||
*
|
||||
* Note that this function will do no operation if called when there is no player
|
||||
* set yet (e.g. inside enhancer construction) or if enhancer outlived the parent
|
||||
* instance somehow. Both cases are considered to be implementation bug.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void
|
||||
clapper_reactable_queue_remove_sync (ClapperReactable *self, ClapperMediaItem *item)
|
||||
{
|
||||
ClapperQueue *queue;
|
||||
|
||||
g_return_if_fail (CLAPPER_IS_REACTABLE (self));
|
||||
g_return_if_fail (CLAPPER_IS_MEDIA_ITEM (item));
|
||||
|
||||
CLAPPER_REACTABLE_DO_WITH_QUEUE (self, &queue, {
|
||||
clapper_utils_queue_remove_on_main_sync (queue, item);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* clapper_reactable_queue_clear_sync:
|
||||
* @reactable: a #ClapperReactable
|
||||
*
|
||||
* A convenience function that within application main thread synchronously clears
|
||||
* the playback queue of the player that @reactable belongs to.
|
||||
*
|
||||
* Reactable enhancers should only modify the queue from the application
|
||||
* main thread, switching thread either themselves or using this convenience
|
||||
* function that does so.
|
||||
*
|
||||
* Note that this function will do no operation if called when there is no player
|
||||
* set yet (e.g. inside enhancer construction) or if enhancer outlived the parent
|
||||
* instance somehow. Both cases are considered to be implementation bug.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void
|
||||
clapper_reactable_queue_clear_sync (ClapperReactable *self)
|
||||
{
|
||||
ClapperQueue *queue;
|
||||
|
||||
g_return_if_fail (CLAPPER_IS_REACTABLE (self));
|
||||
g_return_if_fail (CLAPPER_IS_MEDIA_ITEM (item));
|
||||
|
||||
CLAPPER_REACTABLE_DO_WITH_QUEUE (self, &queue, {
|
||||
clapper_utils_queue_clear_on_main_sync (queue);
|
||||
});
|
||||
}
|
228
src/lib/clapper/clapper-reactable.h
Normal file
228
src/lib/clapper/clapper-reactable.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/* Clapper Playback Library
|
||||
* Copyright (C) 2025 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLAPPER_INSIDE__) && !defined(CLAPPER_COMPILATION)
|
||||
#error "Only <clapper/clapper.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <clapper/clapper-visibility.h>
|
||||
#include <clapper/clapper-player.h>
|
||||
#include <clapper/clapper-enums.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLAPPER_TYPE_REACTABLE (clapper_reactable_get_type())
|
||||
#define CLAPPER_REACTABLE_CAST(obj) ((ClapperReactable *)(obj))
|
||||
|
||||
CLAPPER_API
|
||||
G_DECLARE_INTERFACE (ClapperReactable, clapper_reactable, CLAPPER, REACTABLE, GstObject)
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface:
|
||||
* @parent_iface: The parent interface structure.
|
||||
* @state_changed: Player state changed.
|
||||
* @position_changed: Player position changed.
|
||||
* @speed_changed: Player speed changed.
|
||||
* @volume_changed: Player volume changed.
|
||||
* @mute_changed: Player mute state changed.
|
||||
* @played_item_changed: New media item started playing.
|
||||
* @item_updated: An item in queue got updated.
|
||||
* @queue_item_added: An item was added to the queue.
|
||||
* @queue_item_removed: An item was removed from queue.
|
||||
* @queue_item_repositioned: An item changed position within queue.
|
||||
* @queue_cleared: All items were removed from queue.
|
||||
* @queue_progression_changed: Progression mode of the queue was changed.
|
||||
*/
|
||||
struct _ClapperReactableInterface
|
||||
{
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::state_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @state: a #ClapperPlayerState
|
||||
*
|
||||
* Player state changed.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* state_changed) (ClapperReactable *reactable, ClapperPlayerState state);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::position_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @position: a decimal number with current position in seconds
|
||||
*
|
||||
* Player position changed.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* position_changed) (ClapperReactable *reactable, gdouble position);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::speed_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @speed: the playback speed multiplier
|
||||
*
|
||||
* Player speed changed.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* speed_changed) (ClapperReactable *reactable, gdouble speed);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::volume_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @volume: the volume level
|
||||
*
|
||||
* Player volume changed.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* volume_changed) (ClapperReactable *reactable, gdouble volume);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::mute_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @mute: %TRUE if player is muted, %FALSE otherwise
|
||||
*
|
||||
* Player mute state changed.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* mute_changed) (ClapperReactable *reactable, gboolean mute);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::played_item_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem that is now playing
|
||||
*
|
||||
* New media item started playing. All following events (such as position changes)
|
||||
* will be related to this @item from now on.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* played_item_changed) (ClapperReactable *reactable, ClapperMediaItem *item);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::item_updated:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem that was updated
|
||||
*
|
||||
* An item in queue got updated.
|
||||
*
|
||||
* This might be (or not) currently played item.
|
||||
* Implementations can compare it against the last item from
|
||||
* [vfunc@Clapper.Reactable.played_item_changed] if they
|
||||
* need to know that.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* item_updated) (ClapperReactable *reactable, ClapperMediaItem *item);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::queue_item_added:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem that was added
|
||||
* @index: position at which @item was placed in queue
|
||||
*
|
||||
* An item was added to the queue.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* queue_item_added) (ClapperReactable *reactable, ClapperMediaItem *item, guint index);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::queue_item_removed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @item: a #ClapperMediaItem that was removed
|
||||
* @index: position from which @item was removed in queue
|
||||
*
|
||||
* An item was removed from queue.
|
||||
*
|
||||
* Implementations that are interested in queue items removal
|
||||
* should also implement [vfunc@Clapper.Reactable.queue_cleared].
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* queue_item_removed) (ClapperReactable *reactable, ClapperMediaItem *item, guint index);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::queue_item_repositioned:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @before: position from which #ClapperMediaItem was removed
|
||||
* @after: position at which #ClapperMediaItem was inserted after removal
|
||||
*
|
||||
* An item changed position within queue.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* queue_item_repositioned) (ClapperReactable *reactable, guint before, guint after);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::queue_cleared:
|
||||
* @reactable: a #ClapperReactable
|
||||
*
|
||||
* All items were removed from queue.
|
||||
*
|
||||
* Note that in such event [vfunc@Clapper.Reactable.queue_item_removed]
|
||||
* will NOT be called for each item for performance reasons. You probably
|
||||
* want to implement this function if you also implemented item removal.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* queue_cleared) (ClapperReactable *reactable);
|
||||
|
||||
/**
|
||||
* ClapperReactableInterface::queue_progression_changed:
|
||||
* @reactable: a #ClapperReactable
|
||||
* @mode: a #ClapperQueueProgressionMode
|
||||
*
|
||||
* Progression mode of the queue was changed.
|
||||
*
|
||||
* Since: 0.10
|
||||
*/
|
||||
void (* queue_progression_changed) (ClapperReactable *reactable, ClapperQueueProgressionMode mode);
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[8];
|
||||
};
|
||||
|
||||
CLAPPER_API
|
||||
ClapperPlayer * clapper_reactable_get_player (ClapperReactable *reactable);
|
||||
|
||||
CLAPPER_API
|
||||
void clapper_reactable_queue_append_sync (ClapperReactable *reactable, ClapperMediaItem *item);
|
||||
|
||||
CLAPPER_API
|
||||
void clapper_reactable_queue_insert_sync (ClapperReactable *reactable, ClapperMediaItem *item, ClapperMediaItem *after_item);
|
||||
|
||||
CLAPPER_API
|
||||
void clapper_reactable_queue_remove_sync (ClapperReactable *reactable, ClapperMediaItem *item);
|
||||
|
||||
CLAPPER_API
|
||||
void clapper_reactable_queue_clear_sync (ClapperReactable *reactable);
|
||||
|
||||
G_END_DECLS
|
@@ -45,6 +45,7 @@
|
||||
#include <clapper/clapper-video-stream.h>
|
||||
|
||||
#include <clapper/clapper-extractable.h>
|
||||
#include <clapper/clapper-reactable.h>
|
||||
|
||||
#include <clapper/clapper-functionalities-availability.h>
|
||||
#include <clapper/features/clapper-features-availability.h>
|
||||
|
@@ -120,6 +120,7 @@ clapper_headers = [
|
||||
'clapper-media-item.h',
|
||||
'clapper-player.h',
|
||||
'clapper-queue.h',
|
||||
'clapper-reactable.h',
|
||||
'clapper-stream.h',
|
||||
'clapper-stream-list.h',
|
||||
'clapper-subtitle-stream.h',
|
||||
@@ -147,6 +148,7 @@ clapper_sources = [
|
||||
'clapper-playbin-bus.c',
|
||||
'clapper-player.c',
|
||||
'clapper-queue.c',
|
||||
'clapper-reactable.c',
|
||||
'clapper-stream.c',
|
||||
'clapper-stream-list.c',
|
||||
'clapper-subtitle-stream.c',
|
||||
|
Reference in New Issue
Block a user