Files
clapper/src/lib/clapper/clapper-features-manager.c
Benjamin A. Beasley b5cc171803 Update LGPL-2.1-or-later license notices for remote-only FSF
The Free Software Foundation is now remote-only, and no longer has a
street address. Updated license notice text is from
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html#SEC4.
2025-06-14 11:35:02 -04:00

371 lines
12 KiB
C

/* Clapper Playback Library
* Copyright (C) 2024 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, see
* <https://www.gnu.org/licenses/>.
*/
#include "clapper-features-manager-private.h"
#include "clapper-features-bus-private.h"
#include "clapper-feature-private.h"
#define GST_CAT_DEFAULT clapper_features_manager_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperFeaturesManager
{
ClapperThreadedObject parent;
GPtrArray *features;
ClapperFeaturesBus *bus;
};
#define parent_class clapper_features_manager_parent_class
G_DEFINE_TYPE (ClapperFeaturesManager, clapper_features_manager, CLAPPER_TYPE_THREADED_OBJECT);
static inline void
_post_object (ClapperFeaturesManager *self, ClapperFeaturesManagerEvent event, GObject *data)
{
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_OBJECT);
g_value_set_object (&value, data);
clapper_features_bus_post_event (self->bus, self, event, &value, NULL);
}
static inline void
_post_int (ClapperFeaturesManager *self, ClapperFeaturesManagerEvent event, gint data)
{
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, data);
clapper_features_bus_post_event (self->bus, self, event, &value, NULL);
}
static inline void
_post_double (ClapperFeaturesManager *self, ClapperFeaturesManagerEvent event, gdouble data)
{
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_DOUBLE);
g_value_set_double (&value, data);
clapper_features_bus_post_event (self->bus, self, event, &value, NULL);
}
static inline void
_post_boolean (ClapperFeaturesManager *self, ClapperFeaturesManagerEvent event, gboolean data)
{
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, data);
clapper_features_bus_post_event (self->bus, self, event, &value, NULL);
}
static inline void
_post_item_added_or_removed (ClapperFeaturesManager *self, ClapperFeaturesManagerEvent event,
ClapperMediaItem *item, guint index)
{
GValue value = G_VALUE_INIT;
GValue extra_value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_OBJECT);
g_value_set_object (&value, (GObject *) item);
g_value_init (&extra_value, G_TYPE_UINT);
g_value_set_uint (&extra_value, index);
clapper_features_bus_post_event (self->bus, self, event, &value, &extra_value);
}
static inline void
_post_item_reposition (ClapperFeaturesManager *self, guint data_1, guint data_2)
{
GValue value = G_VALUE_INIT;
GValue extra_value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, data_1);
g_value_init (&extra_value, G_TYPE_UINT);
g_value_set_uint (&extra_value, data_2);
clapper_features_bus_post_event (self->bus, self,
CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_ITEM_REPOSITIONED, &value, &extra_value);
}
/*
* clapper_features_manager_new:
*
* Returns: (transfer full): a new #ClapperFeaturesManager instance.
*/
ClapperFeaturesManager *
clapper_features_manager_new (void)
{
ClapperFeaturesManager *features_manager;
features_manager = g_object_new (CLAPPER_TYPE_FEATURES_MANAGER, NULL);
gst_object_ref_sink (features_manager);
return features_manager;
}
void
clapper_features_manager_add_feature (ClapperFeaturesManager *self, ClapperFeature *feature, GstObject *parent)
{
GValue value = G_VALUE_INIT;
GValue extra_value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_OBJECT);
g_value_set_object (&value, G_OBJECT (feature));
g_value_init (&extra_value, G_TYPE_OBJECT);
g_value_set_object (&extra_value, G_OBJECT (parent));
clapper_features_bus_post_event (self->bus, self,
CLAPPER_FEATURES_MANAGER_EVENT_FEATURE_ADDED, &value, &extra_value);
}
void
clapper_features_manager_trigger_property_changed (ClapperFeaturesManager *self, ClapperFeature *feature, GParamSpec *pspec)
{
GValue value = G_VALUE_INIT;
GValue extra_value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_OBJECT);
g_value_set_object (&value, G_OBJECT (feature));
g_value_init (&extra_value, G_TYPE_PARAM);
g_value_set_param (&extra_value, pspec);
clapper_features_bus_post_event (self->bus, self,
CLAPPER_FEATURES_MANAGER_EVENT_FEATURE_PROPERTY_CHANGED, &value, &extra_value);
}
void
clapper_features_manager_trigger_state_changed (ClapperFeaturesManager *self, ClapperPlayerState state)
{
_post_int (self, CLAPPER_FEATURES_MANAGER_EVENT_STATE_CHANGED, state);
}
void
clapper_features_manager_trigger_position_changed (ClapperFeaturesManager *self, gdouble position)
{
_post_double (self, CLAPPER_FEATURES_MANAGER_EVENT_POSITION_CHANGED, position);
}
void
clapper_features_manager_trigger_speed_changed (ClapperFeaturesManager *self, gdouble speed)
{
_post_double (self, CLAPPER_FEATURES_MANAGER_EVENT_SPEED_CHANGED, speed);
}
void
clapper_features_manager_trigger_volume_changed (ClapperFeaturesManager *self, gdouble volume)
{
_post_double (self, CLAPPER_FEATURES_MANAGER_EVENT_VOLUME_CHANGED, volume);
}
void
clapper_features_manager_trigger_mute_changed (ClapperFeaturesManager *self, gboolean mute)
{
_post_boolean (self, CLAPPER_FEATURES_MANAGER_EVENT_MUTE_CHANGED, mute);
}
void
clapper_features_manager_trigger_played_item_changed (ClapperFeaturesManager *self, ClapperMediaItem *item)
{
_post_object (self, CLAPPER_FEATURES_MANAGER_EVENT_PLAYED_ITEM_CHANGED, (GObject *) item);
}
void
clapper_features_manager_trigger_item_updated (ClapperFeaturesManager *self, ClapperMediaItem *item)
{
_post_object (self, CLAPPER_FEATURES_MANAGER_EVENT_ITEM_UPDATED, (GObject *) item);
}
void
clapper_features_manager_trigger_queue_item_added (ClapperFeaturesManager *self, ClapperMediaItem *item, guint index)
{
_post_item_added_or_removed (self, CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_ITEM_ADDED, item, index);
}
void
clapper_features_manager_trigger_queue_item_removed (ClapperFeaturesManager *self, ClapperMediaItem *item, guint index)
{
_post_item_added_or_removed (self, CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_ITEM_REMOVED, item, index);
}
void
clapper_features_manager_trigger_queue_item_repositioned (ClapperFeaturesManager *self, guint before, guint after)
{
_post_item_reposition (self, before, after);
}
void
clapper_features_manager_trigger_queue_cleared (ClapperFeaturesManager *self)
{
clapper_features_bus_post_event (self->bus, self, CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_CLEARED, NULL, NULL);
}
void
clapper_features_manager_trigger_queue_progression_changed (ClapperFeaturesManager *self, ClapperQueueProgressionMode mode)
{
_post_int (self, CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_PROGRESSION_CHANGED, mode);
}
void
clapper_features_manager_handle_event (ClapperFeaturesManager *self, ClapperFeaturesManagerEvent event,
const GValue *value, const GValue *extra_value)
{
guint i;
switch (event) {
case CLAPPER_FEATURES_MANAGER_EVENT_FEATURE_ADDED:{
ClapperFeature *feature = g_value_get_object (value);
GstObject *parent = g_value_get_object (extra_value);
if (!g_ptr_array_find (self->features, feature, NULL)) {
g_ptr_array_add (self->features, gst_object_ref (feature));
gst_object_set_parent (GST_OBJECT_CAST (feature), parent);
clapper_feature_call_prepare (feature);
}
/* Nothing more to do */
return;
}
default:
break;
}
for (i = 0; i < self->features->len; ++i) {
ClapperFeature *feature = g_ptr_array_index (self->features, i);
switch (event) {
case CLAPPER_FEATURES_MANAGER_EVENT_FEATURE_PROPERTY_CHANGED:{
ClapperFeature *event_feature = g_value_get_object (value);
if (feature == event_feature) {
clapper_feature_call_property_changed (feature,
g_value_get_param (extra_value));
}
break;
}
case CLAPPER_FEATURES_MANAGER_EVENT_STATE_CHANGED:
clapper_feature_call_state_changed (feature, g_value_get_int (value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_POSITION_CHANGED:
clapper_feature_call_position_changed (feature, g_value_get_double (value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_SPEED_CHANGED:
clapper_feature_call_speed_changed (feature, g_value_get_double (value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_VOLUME_CHANGED:
clapper_feature_call_volume_changed (feature, g_value_get_double (value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_MUTE_CHANGED:
clapper_feature_call_mute_changed (feature, g_value_get_boolean (value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_PLAYED_ITEM_CHANGED:
clapper_feature_call_played_item_changed (feature,
CLAPPER_MEDIA_ITEM_CAST (g_value_get_object (value)));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_ITEM_UPDATED:
clapper_feature_call_item_updated (feature,
CLAPPER_MEDIA_ITEM_CAST (g_value_get_object (value)));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_ITEM_ADDED:
clapper_feature_call_queue_item_added (feature,
CLAPPER_MEDIA_ITEM_CAST (g_value_get_object (value)),
g_value_get_uint (extra_value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_ITEM_REMOVED:
clapper_feature_call_queue_item_removed (feature,
CLAPPER_MEDIA_ITEM_CAST (g_value_get_object (value)),
g_value_get_uint (extra_value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_ITEM_REPOSITIONED:
clapper_feature_call_queue_item_repositioned (feature,
g_value_get_uint (value),
g_value_get_uint (extra_value));
break;
case CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_CLEARED:
clapper_feature_call_queue_cleared (feature);
break;
case CLAPPER_FEATURES_MANAGER_EVENT_QUEUE_PROGRESSION_CHANGED:
clapper_feature_call_queue_progression_changed (feature, g_value_get_int (value));
break;
default:
break;
}
}
}
static void
clapper_features_manager_thread_start (ClapperThreadedObject *threaded_object)
{
ClapperFeaturesManager *self = CLAPPER_FEATURES_MANAGER_CAST (threaded_object);
GST_TRACE_OBJECT (threaded_object, "Features manager thread start");
self->features = g_ptr_array_new_with_free_func (
(GDestroyNotify) gst_object_unref);
self->bus = clapper_features_bus_new ();
}
static void
clapper_features_manager_thread_stop (ClapperThreadedObject *threaded_object)
{
ClapperFeaturesManager *self = CLAPPER_FEATURES_MANAGER_CAST (threaded_object);
guint i;
GST_TRACE_OBJECT (threaded_object, "Features manager thread stop");
gst_bus_set_flushing (GST_BUS_CAST (self->bus), TRUE);
gst_bus_remove_watch (GST_BUS_CAST (self->bus));
gst_clear_object (&self->bus);
for (i = 0; i < self->features->len; ++i) {
ClapperFeature *feature = g_ptr_array_index (self->features, i);
clapper_feature_call_unprepare (feature);
gst_object_unparent (GST_OBJECT_CAST (feature));
}
g_ptr_array_unref (self->features);
}
static void
clapper_features_manager_init (ClapperFeaturesManager *self)
{
}
static void
clapper_features_manager_class_init (ClapperFeaturesManagerClass *klass)
{
ClapperThreadedObjectClass *threaded_object = (ClapperThreadedObjectClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperfeaturesmanager", 0,
"Clapper Features Manager");
threaded_object->thread_start = clapper_features_manager_thread_start;
threaded_object->thread_stop = clapper_features_manager_thread_stop;
}