1 /* GStreamer
2 *
3 * Copyright (C) 2014-2015 Sebastian Dröge <sebastian@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 /**
22 * SECTION:gstplayer-gmaincontextsignaldispatcher
23 * @title: GstPlayerGMainContextSignalDispatcher
24 * @short_description: Player GLib MainContext dispatcher
25 *
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "gstplayer-g-main-context-signal-dispatcher.h"
33
34 struct _GstPlayerGMainContextSignalDispatcher
35 {
36 GObject parent;
37 GMainContext *application_context;
38 };
39
40 struct _GstPlayerGMainContextSignalDispatcherClass
41 {
42 GObjectClass parent_class;
43 };
44
45 static void
46 gst_player_g_main_context_signal_dispatcher_interface_init
47 (GstPlayerSignalDispatcherInterface * iface);
48
49 enum
50 {
51 G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_0,
52 G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT,
53 G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_LAST
54 };
55
56 G_DEFINE_TYPE_WITH_CODE (GstPlayerGMainContextSignalDispatcher,
57 gst_player_g_main_context_signal_dispatcher, G_TYPE_OBJECT,
58 G_IMPLEMENT_INTERFACE (GST_TYPE_PLAYER_SIGNAL_DISPATCHER,
59 gst_player_g_main_context_signal_dispatcher_interface_init));
60
61 static GParamSpec
62 * g_main_context_signal_dispatcher_param_specs
63 [G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_LAST] = { NULL, };
64
65 static void
gst_player_g_main_context_signal_dispatcher_finalize(GObject * object)66 gst_player_g_main_context_signal_dispatcher_finalize (GObject * object)
67 {
68 GstPlayerGMainContextSignalDispatcher *self =
69 GST_PLAYER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (object);
70
71 if (self->application_context)
72 g_main_context_unref (self->application_context);
73
74 G_OBJECT_CLASS
75 (gst_player_g_main_context_signal_dispatcher_parent_class)->finalize
76 (object);
77 }
78
79 static void
gst_player_g_main_context_signal_dispatcher_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)80 gst_player_g_main_context_signal_dispatcher_set_property (GObject * object,
81 guint prop_id, const GValue * value, GParamSpec * pspec)
82 {
83 GstPlayerGMainContextSignalDispatcher *self =
84 GST_PLAYER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (object);
85
86 switch (prop_id) {
87 case G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT:
88 self->application_context = g_value_dup_boxed (value);
89 if (!self->application_context)
90 self->application_context = g_main_context_ref_thread_default ();
91 break;
92 default:
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
94 break;
95 }
96 }
97
98 static void
gst_player_g_main_context_signal_dispatcher_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)99 gst_player_g_main_context_signal_dispatcher_get_property (GObject * object,
100 guint prop_id, GValue * value, GParamSpec * pspec)
101 {
102 GstPlayerGMainContextSignalDispatcher *self =
103 GST_PLAYER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (object);
104
105 switch (prop_id) {
106 case G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT:
107 g_value_set_boxed (value, self->application_context);
108 break;
109 default:
110 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111 break;
112 }
113 }
114
115 static void
gst_player_g_main_context_signal_dispatcher_class_init(GstPlayerGMainContextSignalDispatcherClass * klass)116 gst_player_g_main_context_signal_dispatcher_class_init
117 (GstPlayerGMainContextSignalDispatcherClass * klass)
118 {
119 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
120
121 gobject_class->finalize =
122 gst_player_g_main_context_signal_dispatcher_finalize;
123 gobject_class->set_property =
124 gst_player_g_main_context_signal_dispatcher_set_property;
125 gobject_class->get_property =
126 gst_player_g_main_context_signal_dispatcher_get_property;
127
128 g_main_context_signal_dispatcher_param_specs
129 [G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT] =
130 g_param_spec_boxed ("application-context", "Application Context",
131 "Application GMainContext to dispatch signals to", G_TYPE_MAIN_CONTEXT,
132 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
133
134 g_object_class_install_properties (gobject_class,
135 G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_LAST,
136 g_main_context_signal_dispatcher_param_specs);
137 }
138
139 static void
gst_player_g_main_context_signal_dispatcher_init(G_GNUC_UNUSED GstPlayerGMainContextSignalDispatcher * self)140 gst_player_g_main_context_signal_dispatcher_init
141 (G_GNUC_UNUSED GstPlayerGMainContextSignalDispatcher * self)
142 {
143 }
144
145 typedef struct
146 {
147 void (*emitter) (gpointer data);
148 gpointer data;
149 GDestroyNotify destroy;
150 } GMainContextSignalDispatcherData;
151
152 static gboolean
g_main_context_signal_dispatcher_dispatch_gsourcefunc(gpointer user_data)153 g_main_context_signal_dispatcher_dispatch_gsourcefunc (gpointer user_data)
154 {
155 GMainContextSignalDispatcherData *data = user_data;
156
157 data->emitter (data->data);
158
159 return G_SOURCE_REMOVE;
160 }
161
162 static void
g_main_context_signal_dispatcher_dispatch_destroy(gpointer user_data)163 g_main_context_signal_dispatcher_dispatch_destroy (gpointer user_data)
164 {
165 GMainContextSignalDispatcherData *data = user_data;
166
167 if (data->destroy)
168 data->destroy (data->data);
169 g_free (data);
170 }
171
172 static void
gst_player_g_main_context_signal_dispatcher_dispatch(GstPlayerSignalDispatcher * iface,G_GNUC_UNUSED GstPlayer * player,void (* emitter)(gpointer data),gpointer data,GDestroyNotify destroy)173 gst_player_g_main_context_signal_dispatcher_dispatch (GstPlayerSignalDispatcher
174 * iface, G_GNUC_UNUSED GstPlayer * player, void (*emitter) (gpointer data),
175 gpointer data, GDestroyNotify destroy)
176 {
177 GstPlayerGMainContextSignalDispatcher *self =
178 GST_PLAYER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (iface);
179 GMainContextSignalDispatcherData *gsourcefunc_data =
180 g_new (GMainContextSignalDispatcherData, 1);
181
182 gsourcefunc_data->emitter = emitter;
183 gsourcefunc_data->data = data;
184 gsourcefunc_data->destroy = destroy;
185
186 g_main_context_invoke_full (self->application_context,
187 G_PRIORITY_DEFAULT, g_main_context_signal_dispatcher_dispatch_gsourcefunc,
188 gsourcefunc_data, g_main_context_signal_dispatcher_dispatch_destroy);
189 }
190
191 static void
gst_player_g_main_context_signal_dispatcher_interface_init(GstPlayerSignalDispatcherInterface * iface)192 gst_player_g_main_context_signal_dispatcher_interface_init
193 (GstPlayerSignalDispatcherInterface * iface)
194 {
195 iface->dispatch = gst_player_g_main_context_signal_dispatcher_dispatch;
196 }
197
198 /**
199 * gst_player_g_main_context_signal_dispatcher_new:
200 * @application_context: (allow-none): GMainContext to use or %NULL
201 *
202 * Creates a new GstPlayerSignalDispatcher that uses @application_context,
203 * or the thread default one if %NULL is used. See gst_player_new().
204 *
205 * Returns: (transfer full): the new GstPlayerSignalDispatcher
206 */
207 GstPlayerSignalDispatcher *
gst_player_g_main_context_signal_dispatcher_new(GMainContext * application_context)208 gst_player_g_main_context_signal_dispatcher_new (GMainContext *
209 application_context)
210 {
211 return g_object_new (GST_TYPE_PLAYER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER,
212 "application-context", application_context, NULL);
213 }
214