2 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
20 * SECTION:rtsp-mount-points
21 * @short_description: Map a path to media
22 * @see_also: #GstRTSPMediaFactory, #GstRTSPClient
24 * A #GstRTSPMountPoints object maintains a relation between paths
25 * and #GstRTSPMediaFactory objects. This object is usually given to
26 * #GstRTSPClient and used to find the media attached to a path.
28 * With gst_rtsp_mount_points_add_factory () and
29 * gst_rtsp_mount_points_remove_factory(), factories can be added and
32 * With gst_rtsp_mount_points_match() you can find the #GstRTSPMediaFactory
33 * object that completely matches the given path.
35 * Last reviewed on 2013-07-11 (1.0.0)
39 #include "rtsp-mount-points.h"
41 #define GST_RTSP_MOUNT_POINTS_GET_PRIVATE(obj) \
42 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MOUNT_POINTS, GstRTSPMountPointsPrivate))
48 GstRTSPMediaFactory *factory;
52 data_item_new (gchar * path, gint len, GstRTSPMediaFactory * factory)
56 item = g_slice_alloc (sizeof (DataItem));
59 item->factory = factory;
65 data_item_free (gpointer data)
67 DataItem *item = data;
70 g_object_unref (item->factory);
71 g_slice_free1 (sizeof (DataItem), item);
75 data_item_dump (gconstpointer a, gconstpointer prefix)
77 const DataItem *item = a;
79 GST_DEBUG ("%s%s %p", (gchar *) prefix, item->path, item->factory);
83 data_item_compare (gconstpointer a, gconstpointer b, gpointer user_data)
85 const DataItem *item1 = a, *item2 = b;
88 res = g_strcmp0 (item1->path, item2->path);
93 struct _GstRTSPMountPointsPrivate
96 GSequence *mounts; /* protected by lock */
100 G_DEFINE_TYPE (GstRTSPMountPoints, gst_rtsp_mount_points, G_TYPE_OBJECT);
102 GST_DEBUG_CATEGORY_STATIC (rtsp_media_debug);
103 #define GST_CAT_DEFAULT rtsp_media_debug
105 static gchar *default_make_path (GstRTSPMountPoints * mounts,
106 const GstRTSPUrl * url);
107 static void gst_rtsp_mount_points_finalize (GObject * obj);
110 gst_rtsp_mount_points_class_init (GstRTSPMountPointsClass * klass)
112 GObjectClass *gobject_class;
114 g_type_class_add_private (klass, sizeof (GstRTSPMountPointsPrivate));
116 gobject_class = G_OBJECT_CLASS (klass);
118 gobject_class->finalize = gst_rtsp_mount_points_finalize;
120 klass->make_path = default_make_path;
122 GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmountpoints", 0,
123 "GstRTSPMountPoints");
127 gst_rtsp_mount_points_init (GstRTSPMountPoints * mounts)
129 GstRTSPMountPointsPrivate *priv = GST_RTSP_MOUNT_POINTS_GET_PRIVATE (mounts);
131 GST_DEBUG_OBJECT (mounts, "created");
135 g_mutex_init (&priv->lock);
136 priv->mounts = g_sequence_new (data_item_free);
141 gst_rtsp_mount_points_finalize (GObject * obj)
143 GstRTSPMountPoints *mounts = GST_RTSP_MOUNT_POINTS (obj);
144 GstRTSPMountPointsPrivate *priv = mounts->priv;
146 GST_DEBUG_OBJECT (mounts, "finalized");
148 g_sequence_free (priv->mounts);
149 g_mutex_clear (&priv->lock);
151 G_OBJECT_CLASS (gst_rtsp_mount_points_parent_class)->finalize (obj);
155 * gst_rtsp_mount_points_new:
157 * Make a new mount points object.
159 * Returns: (transfer full): a new #GstRTSPMountPoints
162 gst_rtsp_mount_points_new (void)
164 GstRTSPMountPoints *result;
166 result = g_object_new (GST_TYPE_RTSP_MOUNT_POINTS, NULL);
172 default_make_path (GstRTSPMountPoints * mounts, const GstRTSPUrl * url)
174 return g_strdup (url->abspath);
178 * gst_rtsp_mount_points_make_path:
179 * @mounts: a #GstRTSPMountPoints
180 * @url: a #GstRTSPUrl
182 * Make a path string from @url.
184 * Returns: (transfer full): a path string for @url, g_free() after usage.
187 gst_rtsp_mount_points_make_path (GstRTSPMountPoints * mounts,
188 const GstRTSPUrl * url)
190 GstRTSPMountPointsClass *klass;
193 g_return_val_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts), NULL);
194 g_return_val_if_fail (url != NULL, NULL);
196 klass = GST_RTSP_MOUNT_POINTS_GET_CLASS (mounts);
198 if (klass->make_path)
199 result = klass->make_path (mounts, url);
207 has_prefix (DataItem * str, DataItem * prefix)
209 /* prefix needs to be smaller than str */
210 if (str->len < prefix->len)
213 /* if str is larger, it there should be a / following the prefix */
214 if (str->len > prefix->len && str->path[prefix->len] != '/')
217 return strncmp (str->path, prefix->path, prefix->len) == 0;
221 * gst_rtsp_mount_points_match:
222 * @mounts: a #GstRTSPMountPoints
223 * @path: a mount point
224 * @matched: (out): the amount of @path matched
226 * Find the factory in @mounts that has the longest match with @path.
228 * If @matched is %NULL, @path will match the factory exactly otherwise
229 * the amount of characters that matched is returned in @matched.
231 * Returns: (transfer full): the #GstRTSPMediaFactory for @path.
232 * g_object_unref() after usage.
234 GstRTSPMediaFactory *
235 gst_rtsp_mount_points_match (GstRTSPMountPoints * mounts,
236 const gchar * path, gint * matched)
238 GstRTSPMountPointsPrivate *priv;
239 GstRTSPMediaFactory *result = NULL;
240 GSequenceIter *iter, *best;
241 DataItem item, *ritem;
243 g_return_val_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts), NULL);
244 g_return_val_if_fail (path != NULL, NULL);
248 item.path = (gchar *) path;
249 item.len = strlen (path);
251 g_mutex_lock (&priv->lock);
253 g_sequence_sort (priv->mounts, data_item_compare, mounts);
254 g_sequence_foreach (priv->mounts, (GFunc) data_item_dump,
255 (gpointer) "sort :");
259 /* find the location of the media in the hashtable we only use the absolute
260 * path of the uri to find a media factory. If the factory depends on other
261 * properties found in the url, this method should be overridden. */
262 iter = g_sequence_get_begin_iter (priv->mounts);
264 while (!g_sequence_iter_is_end (iter)) {
265 ritem = g_sequence_get (iter);
267 data_item_dump (ritem, "inspect: ");
270 if (has_prefix (&item, ritem)) {
271 data_item_dump (ritem, "prefix: ");
275 if (!has_prefix (&item, ritem))
279 data_item_dump (ritem, "new best: ");
281 iter = g_sequence_iter_next (iter);
284 ritem = g_sequence_get (best);
285 data_item_dump (ritem, "result: ");
286 if (matched || ritem->len == item.len) {
287 result = g_object_ref (ritem->factory);
289 *matched = ritem->len;
292 g_mutex_unlock (&priv->lock);
294 GST_INFO ("found media factory %p for path %s", result, path);
300 * gst_rtsp_mount_points_add_factory:
301 * @mounts: a #GstRTSPMountPoints
302 * @path: a mount point
303 * @factory: (transfer full): a #GstRTSPMediaFactory
305 * Attach @factory to the mount point @path in @mounts.
307 * @path is of the form (/node)+. Any previous mount point will be freed.
309 * Ownership is taken of the reference on @factory so that @factory should not be
310 * used after calling this function.
313 gst_rtsp_mount_points_add_factory (GstRTSPMountPoints * mounts,
314 const gchar * path, GstRTSPMediaFactory * factory)
316 GstRTSPMountPointsPrivate *priv;
319 g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts));
320 g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
321 g_return_if_fail (path != NULL);
325 item = data_item_new (g_strdup (path), strlen (path), factory);
327 GST_INFO ("adding media factory %p for path %s", factory, path);
329 g_mutex_lock (&priv->lock);
330 g_sequence_append (priv->mounts, item);
332 g_mutex_unlock (&priv->lock);
336 * gst_rtsp_mount_points_remove_factory:
337 * @mounts: a #GstRTSPMountPoints
338 * @path: a mount point
340 * Remove the #GstRTSPMediaFactory associated with @path in @mounts.
343 gst_rtsp_mount_points_remove_factory (GstRTSPMountPoints * mounts,
346 GstRTSPMountPointsPrivate *priv;
350 g_return_if_fail (GST_IS_RTSP_MOUNT_POINTS (mounts));
351 g_return_if_fail (path != NULL);
355 item.path = (gchar *) path;
357 GST_INFO ("removing media factory for path %s", path);
359 g_mutex_lock (&priv->lock);
361 g_sequence_sort (priv->mounts, data_item_compare, mounts);
364 iter = g_sequence_lookup (priv->mounts, &item, data_item_compare, mounts);
366 g_sequence_remove (iter);
369 g_mutex_unlock (&priv->lock);