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.
21 #include "rtsp-session.h"
25 #define DEFAULT_TIMEOUT 60
35 GST_DEBUG_CATEGORY_STATIC (rtsp_session_debug);
36 #define GST_CAT_DEFAULT rtsp_session_debug
38 static void gst_rtsp_session_get_property (GObject * object, guint propid,
39 GValue * value, GParamSpec * pspec);
40 static void gst_rtsp_session_set_property (GObject * object, guint propid,
41 const GValue * value, GParamSpec * pspec);
42 static void gst_rtsp_session_finalize (GObject * obj);
44 G_DEFINE_TYPE (GstRTSPSession, gst_rtsp_session, G_TYPE_OBJECT);
47 gst_rtsp_session_class_init (GstRTSPSessionClass * klass)
49 GObjectClass *gobject_class;
51 gobject_class = G_OBJECT_CLASS (klass);
53 gobject_class->get_property = gst_rtsp_session_get_property;
54 gobject_class->set_property = gst_rtsp_session_set_property;
55 gobject_class->finalize = gst_rtsp_session_finalize;
57 g_object_class_install_property (gobject_class, PROP_SESSIONID,
58 g_param_spec_string ("sessionid", "Sessionid", "the session id",
59 NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
60 G_PARAM_STATIC_STRINGS));
62 g_object_class_install_property (gobject_class, PROP_TIMEOUT,
63 g_param_spec_uint ("timeout", "timeout",
64 "the timeout of the session (0 = never)", 0, G_MAXUINT,
65 DEFAULT_TIMEOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
67 GST_DEBUG_CATEGORY_INIT (rtsp_session_debug, "rtspsession", 0,
72 gst_rtsp_session_init (GstRTSPSession * session)
74 g_mutex_init (&session->lock);
75 session->timeout = DEFAULT_TIMEOUT;
76 g_get_current_time (&session->create_time);
77 gst_rtsp_session_touch (session);
81 gst_rtsp_session_finalize (GObject * obj)
83 GstRTSPSession *session;
85 session = GST_RTSP_SESSION (obj);
87 GST_INFO ("finalize session %p", session);
90 g_list_free_full (session->medias, g_object_unref);
93 g_free (session->sessionid);
94 g_mutex_clear (&session->lock);
96 G_OBJECT_CLASS (gst_rtsp_session_parent_class)->finalize (obj);
100 gst_rtsp_session_get_property (GObject * object, guint propid,
101 GValue * value, GParamSpec * pspec)
103 GstRTSPSession *session = GST_RTSP_SESSION (object);
107 g_value_set_string (value, session->sessionid);
110 g_value_set_uint (value, gst_rtsp_session_get_timeout (session));
113 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
118 gst_rtsp_session_set_property (GObject * object, guint propid,
119 const GValue * value, GParamSpec * pspec)
121 GstRTSPSession *session = GST_RTSP_SESSION (object);
125 g_free (session->sessionid);
126 session->sessionid = g_value_dup_string (value);
129 gst_rtsp_session_set_timeout (session, g_value_get_uint (value));
132 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
137 * gst_rtsp_session_manage_media:
138 * @sess: a #GstRTSPSession
139 * @uri: the uri for the media
140 * @media: (transfer full): a #GstRTSPMedia
142 * Manage the media object @obj in @sess. @uri will be used to retrieve this
143 * media from the session with gst_rtsp_session_get_media().
145 * Ownership is taken from @media.
147 * Returns: (transfer none): a new @GstRTSPSessionMedia object.
149 GstRTSPSessionMedia *
150 gst_rtsp_session_manage_media (GstRTSPSession * sess, const GstRTSPUrl * uri,
151 GstRTSPMedia * media)
153 GstRTSPSessionMedia *result;
155 g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
156 g_return_val_if_fail (uri != NULL, NULL);
157 g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
158 g_return_val_if_fail (media->status == GST_RTSP_MEDIA_STATUS_PREPARED, NULL);
160 result = gst_rtsp_session_media_new (uri, media);
162 g_mutex_lock (&sess->lock);
163 sess->medias = g_list_prepend (sess->medias, result);
164 g_mutex_unlock (&sess->lock);
166 GST_INFO ("manage new media %p in session %p", media, result);
172 * gst_rtsp_session_release_media:
173 * @sess: a #GstRTSPSession
174 * @media: a #GstRTSPMedia
176 * Release the managed @media in @sess, freeing the memory allocated by it.
178 * Returns: %TRUE if there are more media session left in @sess.
181 gst_rtsp_session_release_media (GstRTSPSession * sess,
182 GstRTSPSessionMedia * media)
187 g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), FALSE);
188 g_return_val_if_fail (media != NULL, FALSE);
190 g_mutex_lock (&sess->lock);
191 find = g_list_find (sess->medias, media);
193 sess->medias = g_list_delete_link (sess->medias, find);
194 more = (sess->medias != NULL);
195 g_mutex_unlock (&sess->lock);
198 g_object_unref (media);
204 * gst_rtsp_session_get_media:
205 * @sess: a #GstRTSPSession
206 * @url: the url for the media
208 * Get the session media of the @url.
210 * Returns: (transfer none): the configuration for @url in @sess.
212 GstRTSPSessionMedia *
213 gst_rtsp_session_get_media (GstRTSPSession * sess, const GstRTSPUrl * url)
215 GstRTSPSessionMedia *result;
218 g_return_val_if_fail (GST_IS_RTSP_SESSION (sess), NULL);
219 g_return_val_if_fail (url != NULL, NULL);
223 g_mutex_lock (&sess->lock);
224 for (walk = sess->medias; walk; walk = g_list_next (walk)) {
225 result = (GstRTSPSessionMedia *) walk->data;
227 if (g_str_equal (result->url->abspath, url->abspath))
232 g_mutex_unlock (&sess->lock);
238 * gst_rtsp_session_new:
239 * @sessionid: a session id
241 * Create a new #GstRTSPSession instance with @sessionid.
244 gst_rtsp_session_new (const gchar * sessionid)
246 GstRTSPSession *result;
248 g_return_val_if_fail (sessionid != NULL, NULL);
250 result = g_object_new (GST_TYPE_RTSP_SESSION, "sessionid", sessionid, NULL);
256 * gst_rtsp_session_get_sessionid:
257 * @session: a #GstRTSPSession
259 * Get the sessionid of @session.
261 * Returns: the sessionid of @session. The value remains valid as long as
265 gst_rtsp_session_get_sessionid (GstRTSPSession * session)
267 g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL);
269 return session->sessionid;
273 * gst_rtsp_session_get_header:
274 * @session: a #GstRTSPSession
276 * Get the string that can be placed in the Session header field.
278 * Returns: (transfer full): the Session header of @session. g_free() after usage.
281 gst_rtsp_session_get_header (GstRTSPSession * session)
285 g_return_val_if_fail (GST_IS_RTSP_SESSION (session), NULL);
287 g_mutex_lock (&session->lock);
288 if (session->timeout != 60)
289 result = g_strdup_printf ("%s; timeout=%d", session->sessionid,
292 result = g_strdup (session->sessionid);
293 g_mutex_unlock (&session->lock);
299 * gst_rtsp_session_set_timeout:
300 * @session: a #GstRTSPSession
301 * @timeout: the new timeout
303 * Configure @session for a timeout of @timeout seconds. The session will be
304 * cleaned up when there is no activity for @timeout seconds.
307 gst_rtsp_session_set_timeout (GstRTSPSession * session, guint timeout)
309 g_return_if_fail (GST_IS_RTSP_SESSION (session));
311 g_mutex_lock (&session->lock);
312 session->timeout = timeout;
313 g_mutex_unlock (&session->lock);
317 * gst_rtsp_session_get_timeout:
318 * @session: a #GstRTSPSession
320 * Get the timeout value of @session.
322 * Returns: the timeout of @session in seconds.
325 gst_rtsp_session_get_timeout (GstRTSPSession * session)
329 g_return_val_if_fail (GST_IS_RTSP_SESSION (session), 0);
331 g_mutex_lock (&session->lock);
332 res = session->timeout;
333 g_mutex_unlock (&session->lock);
339 * gst_rtsp_session_touch:
340 * @session: a #GstRTSPSession
342 * Update the last_access time of the session to the current time.
345 gst_rtsp_session_touch (GstRTSPSession * session)
347 g_return_if_fail (GST_IS_RTSP_SESSION (session));
349 g_mutex_lock (&session->lock);
350 g_get_current_time (&session->last_access);
351 g_mutex_unlock (&session->lock);
355 * gst_rtsp_session_prevent_expire:
356 * @session: a #GstRTSPSession
358 * Prevent @session from expiring.
361 gst_rtsp_session_prevent_expire (GstRTSPSession * session)
363 g_return_if_fail (GST_IS_RTSP_SESSION (session));
365 g_atomic_int_add (&session->expire_count, 1);
369 * gst_rtsp_session_allow_expire:
370 * @session: a #GstRTSPSession
372 * Allow @session to expire. This method must be called an equal
373 * amount of time as gst_rtsp_session_prevent_expire().
376 gst_rtsp_session_allow_expire (GstRTSPSession * session)
378 g_atomic_int_add (&session->expire_count, -1);
382 * gst_rtsp_session_next_timeout:
383 * @session: a #GstRTSPSession
384 * @now: the current system time
386 * Get the amount of milliseconds till the session will expire.
388 * Returns: the amount of milliseconds since the session will time out.
391 gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now)
394 GstClockTime last_access, now_ns;
396 g_return_val_if_fail (GST_IS_RTSP_SESSION (session), -1);
397 g_return_val_if_fail (now != NULL, -1);
399 g_mutex_lock (&session->lock);
400 if (g_atomic_int_get (&session->expire_count) != 0) {
401 /* touch session when the expire count is not 0 */
402 g_get_current_time (&session->last_access);
405 last_access = GST_TIMEVAL_TO_TIME (session->last_access);
406 /* add timeout allow for 5 seconds of extra time */
407 last_access += session->timeout * GST_SECOND + (5 * GST_SECOND);
408 g_mutex_unlock (&session->lock);
410 now_ns = GST_TIMEVAL_TO_TIME (*now);
412 if (last_access > now_ns)
413 res = GST_TIME_AS_MSECONDS (last_access - now_ns);
421 * gst_rtsp_session_is_expired:
422 * @session: a #GstRTSPSession
423 * @now: the current system time
425 * Check if @session timeout out.
427 * Returns: %TRUE if @session timed out
430 gst_rtsp_session_is_expired (GstRTSPSession * session, GTimeVal * now)
434 res = (gst_rtsp_session_next_timeout (session, now) == 0);