Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-media-adapter"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <libvalent-core.h>
9 : :
10 : : #include "valent-media-player.h"
11 : : #include "valent-media-adapter.h"
12 : :
13 : :
14 : : /**
15 : : * ValentMediaAdapter:
16 : : *
17 : : * An abstract base class for media player adapters.
18 : : *
19 : : * `ValentMediaAdapter` is a base class for plugins that provide an interface to
20 : : * manage media players. This usually means monitoring and querying instances of
21 : : * [class@Valent.MediaPlayer].
22 : : *
23 : : * ## `.plugin` File
24 : : *
25 : : * Implementations may define the following extra fields in the `.plugin` file:
26 : : *
27 : : * - `X-MediaAdapterPriority`
28 : : *
29 : : * An integer indicating the adapter priority. The implementation with the
30 : : * lowest value will be used as the primary adapter.
31 : : *
32 : : * Since: 1.0
33 : : */
34 : :
35 : : typedef struct
36 : : {
37 : : GPtrArray *players;
38 : : } ValentMediaAdapterPrivate;
39 : :
40 : : static void g_list_model_iface_init (GListModelInterface *iface);
41 : :
42 [ + + + - ]: 572 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ValentMediaAdapter, valent_media_adapter, VALENT_TYPE_EXTENSION,
43 : : G_ADD_PRIVATE (ValentMediaAdapter)
44 : : G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, g_list_model_iface_init))
45 : :
46 : : /**
47 : : * ValentMediaAdapterClass:
48 : : * @export_player: the virtual function pointer for valent_media_adapter_export()
49 : : * @unexport_player: the virtual function pointer for valent_media_adapter_unexport()
50 : : *
51 : : * The virtual function table for `ValentMediaAdapter`.
52 : : */
53 : :
54 : :
55 : : /*
56 : : * GListModel
57 : : */
58 : : static gpointer
59 : 9 : valent_media_adapter_get_item (GListModel *list,
60 : : unsigned int position)
61 : : {
62 : 9 : ValentMediaAdapter *self = VALENT_MEDIA_ADAPTER (list);
63 : 9 : ValentMediaAdapterPrivate *priv = valent_media_adapter_get_instance_private (self);
64 : :
65 [ + - ]: 9 : g_assert (VALENT_IS_MEDIA_ADAPTER (self));
66 : :
67 [ + - ]: 9 : if G_UNLIKELY (position >= priv->players->len)
68 : : return NULL;
69 : :
70 : 9 : return g_object_ref (g_ptr_array_index (priv->players, position));
71 : : }
72 : :
73 : : static GType
74 : 0 : valent_media_adapter_get_item_type (GListModel *list)
75 : : {
76 : 0 : return VALENT_TYPE_MEDIA_ADAPTER;
77 : : }
78 : :
79 : : static unsigned int
80 : 41 : valent_media_adapter_get_n_items (GListModel *list)
81 : : {
82 : 41 : ValentMediaAdapter *self = VALENT_MEDIA_ADAPTER (list);
83 : 41 : ValentMediaAdapterPrivate *priv = valent_media_adapter_get_instance_private (self);
84 : :
85 [ + - ]: 41 : g_assert (VALENT_IS_MEDIA_ADAPTER (self));
86 : :
87 : 41 : return priv->players->len;
88 : : }
89 : :
90 : : static void
91 : 58 : g_list_model_iface_init (GListModelInterface *iface)
92 : : {
93 : 58 : iface->get_item = valent_media_adapter_get_item;
94 : 58 : iface->get_item_type = valent_media_adapter_get_item_type;
95 : 58 : iface->get_n_items = valent_media_adapter_get_n_items;
96 : 58 : }
97 : :
98 : : /* LCOV_EXCL_START */
99 : : static void
100 : : valent_media_adapter_real_export_player (ValentMediaAdapter *adapter,
101 : : ValentMediaPlayer *player)
102 : : {
103 : : g_assert (VALENT_IS_MEDIA_ADAPTER (adapter));
104 : : g_assert (VALENT_IS_MEDIA_PLAYER (player));
105 : : }
106 : :
107 : : static void
108 : : valent_media_adapter_real_unexport_player (ValentMediaAdapter *adapter,
109 : : ValentMediaPlayer *player)
110 : : {
111 : : g_assert (VALENT_IS_MEDIA_ADAPTER (adapter));
112 : : g_assert (VALENT_IS_MEDIA_PLAYER (player));
113 : : }
114 : : /* LCOV_EXCL_STOP */
115 : :
116 : : /*
117 : : * GObject
118 : : */
119 : : static void
120 : 16 : valent_media_adapter_finalize (GObject *object)
121 : : {
122 : 16 : ValentMediaAdapter *self = VALENT_MEDIA_ADAPTER (object);
123 : 16 : ValentMediaAdapterPrivate *priv = valent_media_adapter_get_instance_private (self);
124 : :
125 [ + - ]: 16 : g_clear_pointer (&priv->players, g_ptr_array_unref);
126 : :
127 : 16 : G_OBJECT_CLASS (valent_media_adapter_parent_class)->finalize (object);
128 : 16 : }
129 : :
130 : : static void
131 : 58 : valent_media_adapter_class_init (ValentMediaAdapterClass *klass)
132 : : {
133 : 58 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
134 : :
135 : 58 : object_class->finalize = valent_media_adapter_finalize;
136 : :
137 : 58 : klass->export_player = valent_media_adapter_real_export_player;
138 : 58 : klass->unexport_player = valent_media_adapter_real_unexport_player;
139 : : }
140 : :
141 : : static void
142 : 18 : valent_media_adapter_init (ValentMediaAdapter *self)
143 : : {
144 : 18 : ValentMediaAdapterPrivate *priv = valent_media_adapter_get_instance_private (self);
145 : :
146 : 18 : priv->players = g_ptr_array_new_with_free_func (g_object_unref);
147 : 18 : }
148 : :
149 : : /**
150 : : * valent_media_adapter_player_added:
151 : : * @adapter: a `ValentMediaAdapter`
152 : : * @player: a `ValentMediaPlayer`
153 : : *
154 : : * Called when @player has been added to @adapter.
155 : : *
156 : : * This method should only be called by implementations of
157 : : * [class@Valent.MediaAdapter]. @adapter will hold a reference on @player and
158 : : * emit [signal@Gio.ListModel::items-changed].
159 : : *
160 : : * Since: 1.0
161 : : */
162 : : void
163 : 7 : valent_media_adapter_player_added (ValentMediaAdapter *adapter,
164 : : ValentMediaPlayer *player)
165 : : {
166 : 7 : ValentMediaAdapterPrivate *priv = valent_media_adapter_get_instance_private (adapter);
167 : 7 : unsigned int position = 0;
168 : :
169 [ + - ]: 7 : g_return_if_fail (VALENT_IS_MEDIA_ADAPTER (adapter));
170 [ - + ]: 7 : g_return_if_fail (VALENT_IS_MEDIA_PLAYER (player));
171 : :
172 : 7 : position = priv->players->len;
173 : 7 : g_ptr_array_add (priv->players, g_object_ref (player));
174 : 7 : g_list_model_items_changed (G_LIST_MODEL (adapter), position, 0, 1);
175 : : }
176 : :
177 : : /**
178 : : * valent_media_adapter_player_removed:
179 : : * @adapter: a `ValentMediaAdapter`
180 : : * @player: a `ValentMediaPlayer`
181 : : *
182 : : * Called when @player has been removed from @adapter.
183 : : *
184 : : * This method should only be called by implementations of
185 : : * [class@Valent.MediaAdapter]. @adapter will drop its reference on @player
186 : : * and emit [signal@Gio.ListModel::items-changed].
187 : : *
188 : : * Since: 1.0
189 : : */
190 : : void
191 : 7 : valent_media_adapter_player_removed (ValentMediaAdapter *adapter,
192 : : ValentMediaPlayer *player)
193 : : {
194 : 7 : ValentMediaAdapterPrivate *priv = valent_media_adapter_get_instance_private (adapter);
195 : 7 : g_autoptr (ValentMediaPlayer) item = NULL;
196 : 7 : unsigned int position = 0;
197 : :
198 [ + - ]: 7 : g_return_if_fail (VALENT_IS_MEDIA_ADAPTER (adapter));
199 [ - + ]: 7 : g_return_if_fail (VALENT_IS_MEDIA_PLAYER (player));
200 : :
201 [ - + ]: 7 : if (!g_ptr_array_find (priv->players, player, &position))
202 : : {
203 : 0 : g_warning ("No such player \"%s\" found in \"%s\"",
204 : : G_OBJECT_TYPE_NAME (player),
205 : : G_OBJECT_TYPE_NAME (adapter));
206 : 0 : return;
207 : : }
208 : :
209 : 7 : item = g_ptr_array_steal_index (priv->players, position);
210 [ + - ]: 7 : g_list_model_items_changed (G_LIST_MODEL (adapter), position, 1, 0);
211 : : }
212 : :
213 : : /**
214 : : * valent_media_adapter_export_player: (virtual export_player)
215 : : * @adapter: an `ValentMediaAdapter`
216 : : * @player: a `ValentMediaPlayer`
217 : : *
218 : : * Export @player on @adapter.
219 : : *
220 : : * This method is intended to allow device plugins to expose remote media
221 : : * players to the host system. Usually this means exporting an interface on
222 : : * D-Bus or an mDNS service.
223 : : *
224 : : * Implementations must automatically unexport any players when destroyed.
225 : : *
226 : : * Since: 1.0
227 : : */
228 : : void
229 : 14 : valent_media_adapter_export_player (ValentMediaAdapter *adapter,
230 : : ValentMediaPlayer *player)
231 : : {
232 : 14 : VALENT_ENTRY;
233 : :
234 [ + - ]: 14 : g_return_if_fail (VALENT_IS_MEDIA_ADAPTER (adapter));
235 [ - + ]: 14 : g_return_if_fail (VALENT_IS_MEDIA_PLAYER (player));
236 : :
237 : 14 : VALENT_MEDIA_ADAPTER_GET_CLASS (adapter)->export_player (adapter, player);
238 : :
239 : 14 : VALENT_EXIT;
240 : : }
241 : :
242 : : /**
243 : : * valent_media_adapter_unexport_player: (virtual unexport_player)
244 : : * @adapter: an `ValentMediaAdapter`
245 : : * @player: a `ValentMediaPlayer`
246 : : *
247 : : * Unexport @player from @adapter.
248 : : *
249 : : * Since: 1.0
250 : : */
251 : : void
252 : 2 : valent_media_adapter_unexport_player (ValentMediaAdapter *adapter,
253 : : ValentMediaPlayer *player)
254 : : {
255 : 2 : VALENT_ENTRY;
256 : :
257 [ + - ]: 2 : g_return_if_fail (VALENT_IS_MEDIA_ADAPTER (adapter));
258 [ - + ]: 2 : g_return_if_fail (VALENT_IS_MEDIA_PLAYER (player));
259 : :
260 : 2 : VALENT_MEDIA_ADAPTER_GET_CLASS (adapter)->unexport_player (adapter, player);
261 : :
262 : 2 : VALENT_EXIT;
263 : : }
264 : :
|