stream: handle renegotiation

Don't allow multiple connects on a stream, you need to first disconnect.
Make sure we disconnect before reconnecting again in the source.
This commit is contained in:
Wim Taymans 2015-08-25 16:36:01 +02:00
parent e098dde0a3
commit f2c9b6badd
2 changed files with 45 additions and 9 deletions

View file

@ -47,6 +47,7 @@ struct _PinosStreamPrivate
GBytes *format; GBytes *format;
GDBusProxy *source_output; GDBusProxy *source_output;
gboolean disconnecting;
PinosStreamMode mode; PinosStreamMode mode;
GSocket *socket; GSocket *socket;
@ -187,7 +188,7 @@ subscription_cb (PinosSubscribe *subscribe,
switch (flags) { switch (flags) {
case PINOS_SUBSCRIPTION_FLAG_SOURCE_OUTPUT: case PINOS_SUBSCRIPTION_FLAG_SOURCE_OUTPUT:
if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) { if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) {
if (object == priv->source_output) { if (object == priv->source_output && !priv->disconnecting) {
priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "output disappeared"); priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "output disappeared");
stream_set_state (stream, PINOS_STREAM_STATE_ERROR); stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
} }
@ -515,6 +516,8 @@ on_source_output_created (GObject *source_object,
GError *error = NULL; GError *error = NULL;
const gchar *source_output_path; const gchar *source_output_path;
g_assert (context->priv->client == G_DBUS_PROXY (source_object));
ret = g_dbus_proxy_call_finish (context->priv->client, res, &error); ret = g_dbus_proxy_call_finish (context->priv->client, res, &error);
if (ret == NULL) if (ret == NULL)
goto create_failed; goto create_failed;
@ -590,6 +593,7 @@ pinos_stream_connect_capture (PinosStream *stream,
priv = stream->priv; priv = stream->priv;
context = priv->context; context = priv->context;
g_return_val_if_fail (pinos_context_get_state (context) == PINOS_CONTEXT_STATE_READY, FALSE); g_return_val_if_fail (pinos_context_get_state (context) == PINOS_CONTEXT_STATE_READY, FALSE);
g_return_val_if_fail (pinos_stream_get_state (stream) == PINOS_STREAM_STATE_UNCONNECTED, FALSE);
g_free (priv->source_path); g_free (priv->source_path);
priv->source_path = g_strdup (source_path); priv->source_path = g_strdup (source_path);
@ -676,18 +680,28 @@ on_source_output_removed (GObject *source_object,
GVariant *ret; GVariant *ret;
GError *error = NULL; GError *error = NULL;
ret = g_dbus_proxy_call_finish (priv->source_output, res, &error); g_assert (priv->source_output == G_DBUS_PROXY (source_object));
if (ret == NULL) {
priv->disconnecting = FALSE;
g_clear_object (&priv->source_output);
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
if (ret == NULL)
goto proxy_failed;
stream_set_state (stream, PINOS_STREAM_STATE_UNCONNECTED);
g_object_unref (stream);
return;
/* ERRORS */
proxy_failed:
{
priv->error = error; priv->error = error;
stream_set_state (stream, PINOS_STREAM_STATE_ERROR); stream_set_state (stream, PINOS_STREAM_STATE_ERROR);
g_warning ("failed to disconnect: %s", error->message); g_warning ("failed to disconnect: %s", error->message);
g_object_unref (stream); g_object_unref (stream);
return; return;
} }
g_clear_object (&priv->source_output);
stream_set_state (stream, PINOS_STREAM_STATE_UNCONNECTED);
g_object_unref (stream);
} }
static gboolean static gboolean
@ -727,6 +741,9 @@ pinos_stream_disconnect (PinosStream *stream)
g_return_val_if_fail (priv->source_output != NULL, FALSE); g_return_val_if_fail (priv->source_output != NULL, FALSE);
context = priv->context; context = priv->context;
g_return_val_if_fail (pinos_context_get_state (context) >= PINOS_CONTEXT_STATE_READY, FALSE); g_return_val_if_fail (pinos_context_get_state (context) >= PINOS_CONTEXT_STATE_READY, FALSE);
g_return_val_if_fail (!priv->disconnecting, FALSE);
priv->disconnecting = TRUE;
g_main_context_invoke (context->priv->context, g_main_context_invoke (context->priv->context,
(GSourceFunc) do_disconnect, (GSourceFunc) do_disconnect,

View file

@ -258,7 +258,10 @@ on_new_buffer (GObject *gobject,
GError *error = NULL; GError *error = NULL;
GST_LOG_OBJECT (pinossrc, "got new buffer"); GST_LOG_OBJECT (pinossrc, "got new buffer");
pinos_stream_capture_buffer (pinossrc->stream, &pbuf); if (!pinos_stream_capture_buffer (pinossrc->stream, &pbuf)) {
g_warning ("failed to capture buffer");
return;
}
buf = gst_buffer_new (); buf = gst_buffer_new ();
@ -419,6 +422,21 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc)
accepted = g_bytes_new_take (str, strlen (str) + 1); accepted = g_bytes_new_take (str, strlen (str) + 1);
pinos_main_loop_lock (pinossrc->loop); pinos_main_loop_lock (pinossrc->loop);
if (pinos_stream_get_state (pinossrc->stream) != PINOS_STREAM_STATE_UNCONNECTED) {
GST_DEBUG_OBJECT (basesrc, "disconnect capture");
pinos_stream_disconnect (pinossrc->stream);
while (TRUE) {
PinosStreamState state = pinos_stream_get_state (pinossrc->stream);
if (state == PINOS_STREAM_STATE_UNCONNECTED)
break;
if (state == PINOS_STREAM_STATE_ERROR)
goto connect_error;
pinos_main_loop_wait (pinossrc->loop);
}
}
GST_DEBUG_OBJECT (basesrc, "connect capture with path %s", pinossrc->path); GST_DEBUG_OBJECT (basesrc, "connect capture with path %s", pinossrc->path);
pinos_stream_connect_capture (pinossrc->stream, pinossrc->path, 0, accepted); pinos_stream_connect_capture (pinossrc->stream, pinossrc->path, 0, accepted);
@ -524,6 +542,7 @@ gst_pinos_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
if (state != PINOS_STREAM_STATE_STREAMING) if (state != PINOS_STREAM_STATE_STREAMING)
goto streaming_stopped; goto streaming_stopped;
if (pinossrc->current != NULL)
break; break;
} }
pinos_main_loop_unlock (pinossrc->loop); pinos_main_loop_unlock (pinossrc->loop);