+/**
+ * gst_rtsp_media_suspend:
+ * @media: a #GstRTSPMedia
+ *
+ * Suspend @media. The state of the pipeline managed by @media is set to
+ * GST_STATE_NULL but all streams are kept. @media can be prepared again
+ * with gst_rtsp_media_undo_reset()
+ *
+ * @media must be prepared with gst_rtsp_media_prepare();
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+gst_rtsp_media_suspend (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv = media->priv;
+ GstStateChangeReturn ret;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+ GST_FIXME ("suspend for dynamic pipelines needs fixing");
+
+ g_rec_mutex_lock (&priv->state_lock);
+ if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
+ goto not_prepared;
+
+ /* don't attempt to suspend when something is busy */
+ if (priv->n_active > 0)
+ goto done;
+
+ switch (priv->suspend_mode) {
+ case GST_RTSP_SUSPEND_MODE_NONE:
+ GST_DEBUG ("media %p no suspend", media);
+ break;
+ case GST_RTSP_SUSPEND_MODE_PAUSE:
+ GST_DEBUG ("media %p suspend to PAUSED", media);
+ priv->target_state = GST_STATE_PAUSED;
+ ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ goto state_failed;
+ break;
+ case GST_RTSP_SUSPEND_MODE_RESET:
+ GST_DEBUG ("media %p suspend to NULL", media);
+ priv->target_state = GST_STATE_NULL;
+ ret = gst_element_set_state (priv->pipeline, GST_STATE_NULL);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ goto state_failed;
+ break;
+ default:
+ break;
+ }
+ /* let the streams do the state changes freely, if any */
+ media_streams_set_blocked (media, FALSE);
+ priv->status = GST_RTSP_MEDIA_STATUS_SUSPENDED;
+done:
+ g_rec_mutex_unlock (&priv->state_lock);
+
+ return TRUE;
+
+ /* ERRORS */
+not_prepared:
+ {
+ g_rec_mutex_unlock (&priv->state_lock);
+ GST_WARNING ("media %p was not prepared", media);
+ return FALSE;
+ }
+state_failed:
+ {
+ g_rec_mutex_unlock (&priv->state_lock);
+ gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
+ GST_WARNING ("failed changing pipeline's state for media %p", media);
+ return FALSE;
+ }
+}
+
+/**
+ * gst_rtsp_media_unsuspend:
+ * @media: a #GstRTSPMedia
+ *
+ * Unsuspend @media if it was in a suspended state. This method does nothing
+ * when the media was not in the suspended state.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+gst_rtsp_media_unsuspend (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv = media->priv;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+ g_rec_mutex_lock (&priv->state_lock);
+ if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED)
+ goto done;
+
+ switch (priv->suspend_mode) {
+ case GST_RTSP_SUSPEND_MODE_NONE:
+ priv->status = GST_RTSP_MEDIA_STATUS_PREPARED;
+ break;
+ case GST_RTSP_SUSPEND_MODE_PAUSE:
+ priv->status = GST_RTSP_MEDIA_STATUS_PREPARED;
+ break;
+ case GST_RTSP_SUSPEND_MODE_RESET:
+ {
+ priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
+ if (!start_preroll (media))
+ goto start_failed;
+ g_rec_mutex_unlock (&priv->state_lock);
+
+ if (!wait_preroll (media))
+ goto preroll_failed;
+
+ g_rec_mutex_lock (&priv->state_lock);
+ }
+ default:
+ break;
+ }
+done:
+ g_rec_mutex_unlock (&priv->state_lock);
+
+ return TRUE;
+
+ /* ERRORS */
+start_failed:
+ {
+ g_rec_mutex_unlock (&priv->state_lock);
+ GST_WARNING ("failed to preroll pipeline");
+ gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR);
+ return FALSE;
+ }
+preroll_failed:
+ {
+ GST_WARNING ("failed to preroll pipeline");
+ return FALSE;
+ }
+}
+
+/* must be called with state-lock */