From b81d9ed11fae7bee59b67b1aee9927e417666875 Mon Sep 17 00:00:00 2001 From: Michal Ratajsky Date: Thu, 3 Jul 2014 20:48:08 +0200 Subject: PulseAudio and API fixes --- backends/pulse/pulse-connection.c | 170 ++++++++++++++++++++++++++------------ 1 file changed, 118 insertions(+), 52 deletions(-) (limited to 'backends/pulse/pulse-connection.c') diff --git a/backends/pulse/pulse-connection.c b/backends/pulse/pulse-connection.c index 4918299..184047f 100644 --- a/backends/pulse/pulse-connection.c +++ b/backends/pulse/pulse-connection.c @@ -348,9 +348,10 @@ pulse_connection_finalize (GObject *object) g_free (connection->priv->server); - pa_context_unref (connection->priv->context); - pa_proplist_free (connection->priv->proplist); + if (connection->priv->context != NULL) + pa_context_unref (connection->priv->context); + pa_proplist_free (connection->priv->proplist); pa_glib_mainloop_free (connection->priv->mainloop); G_OBJECT_CLASS (pulse_connection_parent_class)->finalize (object); @@ -364,7 +365,6 @@ pulse_connection_new (const gchar *app_name, const gchar *server_address) { pa_glib_mainloop *mainloop; - pa_context *context; pa_proplist *proplist; PulseConnection *connection; @@ -375,11 +375,18 @@ pulse_connection_new (const gchar *app_name, } /* Create a property list to hold information about the application, - * the list will be kept with the connection as it may be reused later - * when creating PulseAudio streams */ + * the list will be kept with the connection as it will be reused later + * when creating PulseAudio contexts and streams */ proplist = pa_proplist_new (); - if (app_name != NULL) + if (app_name != NULL) { pa_proplist_sets (proplist, PA_PROP_APPLICATION_NAME, app_name); + } else { + /* Set a sensible default name when application does not provide one */ + gchar *name = connection_get_app_name (); + + pa_proplist_sets (proplist, PA_PROP_APPLICATION_NAME, name); + g_free (name); + } if (app_id != NULL) pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, app_id); if (app_icon != NULL) @@ -387,62 +394,55 @@ pulse_connection_new (const gchar *app_name, if (app_version != NULL) pa_proplist_sets (proplist, PA_PROP_APPLICATION_VERSION, app_version); - if (app_name != NULL) { - context = pa_context_new_with_proplist (pa_glib_mainloop_get_api (mainloop), - app_name, - proplist); - } else { - /* Try to set some sensible default name when application does not - * provide a name */ - gchar *name = connection_get_app_name (); - - context = pa_context_new_with_proplist (pa_glib_mainloop_get_api (mainloop), - name, - proplist); - g_free (name); - } - - if (G_UNLIKELY (context == NULL)) { - g_warning ("Failed to create PulseAudio context"); - - pa_glib_mainloop_free (mainloop); - pa_proplist_free (proplist); - return NULL; - } - connection = g_object_new (PULSE_TYPE_CONNECTION, "server", server_address, NULL); - /* Set function to monitor status changes */ - pa_context_set_state_callback (context, - connection_state_cb, - connection); - connection->priv->mainloop = mainloop; - connection->priv->context = context; connection->priv->proplist = proplist; return connection; } gboolean -pulse_connection_connect (PulseConnection *connection) +pulse_connection_connect (PulseConnection *connection, gboolean wait_for_daemon) { + pa_context *context; + pa_context_flags_t flags = PA_CONTEXT_NOFLAGS; + pa_mainloop_api *mainloop; + g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); if (connection->priv->state != PULSE_CONNECTION_DISCONNECTED) return TRUE; + mainloop = pa_glib_mainloop_get_api (connection->priv->mainloop); + context = pa_context_new_with_proplist (mainloop, + NULL, + connection->priv->proplist); + if (G_UNLIKELY (context == NULL)) { + g_warning ("Failed to create PulseAudio context"); + return FALSE; + } + + /* Set function to monitor status changes */ + pa_context_set_state_callback (context, + connection_state_cb, + connection); + if (wait_for_daemon) + flags = PA_CONTEXT_NOFAIL; + /* Initiate a connection, state changes will be delivered asynchronously */ - if (pa_context_connect (connection->priv->context, + if (pa_context_connect (context, connection->priv->server, - PA_CONTEXT_NOFLAGS, + flags, NULL) == 0) { - connection->priv->state = PULSE_CONNECTION_CONNECTING; + connection->priv->context = context; + connection_change_state (connection, PULSE_CONNECTION_CONNECTING); return TRUE; } + pa_context_unref (context); return FALSE; } @@ -454,7 +454,10 @@ pulse_connection_disconnect (PulseConnection *connection) if (connection->priv->state == PULSE_CONNECTION_DISCONNECTED) return; - pa_context_disconnect (connection->priv->context); + pa_context_unref (connection->priv->context); + + connection->priv->context = NULL; + connection->priv->outstanding = 0; connection_change_state (connection, PULSE_CONNECTION_DISCONNECTED); } @@ -474,6 +477,9 @@ pulse_connection_create_monitor (PulseConnection *connection, { g_return_val_if_fail (PULSE_IS_CONNECTION (connection), NULL); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return NULL; + return pulse_monitor_new (connection->priv->context, connection->priv->proplist, index_source, @@ -488,6 +494,9 @@ pulse_connection_set_default_sink (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_default_sink (connection->priv->context, name, NULL, NULL); @@ -503,6 +512,9 @@ pulse_connection_set_default_source (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_default_source (connection->priv->context, name, NULL, NULL); @@ -519,6 +531,9 @@ pulse_connection_set_card_profile (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_card_profile_by_name (connection->priv->context, card, profile, @@ -536,6 +551,9 @@ pulse_connection_set_sink_mute (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_sink_mute_by_index (connection->priv->context, index, (int) mute, @@ -553,6 +571,9 @@ pulse_connection_set_sink_volume (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_sink_volume_by_index (connection->priv->context, index, volume, @@ -570,6 +591,9 @@ pulse_connection_set_sink_port (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_sink_port_by_index (connection->priv->context, index, port, @@ -587,6 +611,9 @@ pulse_connection_set_sink_input_mute (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_sink_input_mute (connection->priv->context, index, (int) mute, @@ -604,6 +631,9 @@ pulse_connection_set_sink_input_volume (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_sink_input_volume (connection->priv->context, index, volume, @@ -621,6 +651,9 @@ pulse_connection_set_source_mute (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_source_mute_by_index (connection->priv->context, index, (int) mute, @@ -638,6 +671,9 @@ pulse_connection_set_source_volume (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_source_volume_by_index (connection->priv->context, index, volume, @@ -655,6 +691,9 @@ pulse_connection_set_source_port (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_source_port_by_index (connection->priv->context, index, port, @@ -673,6 +712,9 @@ pulse_connection_set_source_output_mute (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_source_output_mute (connection->priv->context, index, (int) mute, @@ -694,6 +736,9 @@ pulse_connection_set_source_output_volume (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_set_source_output_volume (connection->priv->context, index, volume, @@ -714,6 +759,9 @@ pulse_connection_suspend_sink (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_suspend_sink_by_index (connection->priv->context, index, (int) suspend, @@ -731,6 +779,9 @@ pulse_connection_suspend_source (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_suspend_source_by_index (connection->priv->context, index, (int) suspend, @@ -748,6 +799,9 @@ pulse_connection_move_sink_input (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_move_sink_input_by_index (connection->priv->context, index, sink_index, @@ -765,6 +819,9 @@ pulse_connection_move_source_output (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_move_source_output_by_index (connection->priv->context, index, source_index, @@ -781,6 +838,9 @@ pulse_connection_kill_sink_input (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_kill_sink_input (connection->priv->context, index, NULL, NULL); @@ -796,6 +856,9 @@ pulse_connection_kill_source_output (PulseConnection *connection, g_return_val_if_fail (PULSE_IS_CONNECTION (connection), FALSE); + if (connection->priv->state != PULSE_CONNECTION_CONNECTED) + return FALSE; + op = pa_context_kill_source_output (connection->priv->context, index, NULL, NULL); @@ -826,7 +889,7 @@ connection_load_lists (PulseConnection *connection) GList *ops = NULL; pa_operation *op; - if (G_UNLIKELY (connection->priv->outstanding)) { + if (G_UNLIKELY (connection->priv->outstanding > 0)) { g_warn_if_reached (); return FALSE; } @@ -919,20 +982,20 @@ connection_state_cb (pa_context *c, void *userdata) connection); pa_operation_unref (op); - if (connection_load_lists (connection) == TRUE) + if (connection_load_lists (connection) == TRUE) { connection_change_state (connection, PULSE_CONNECTION_LOADING); - else - pulse_connection_disconnect (connection); - - return; - } + return; + } - /* If we could not subscribe to notifications, we consider it the - * same as a connection failture */ - g_warning ("Failed to subscribe to PulseAudio notifications: %s", - pa_strerror (pa_context_errno (connection->priv->context))); + /* Treat as a connection failure */ + state = PA_CONTEXT_FAILED; + } else { + g_warning ("Failed to subscribe to PulseAudio notifications: %s", + pa_strerror (pa_context_errno (connection->priv->context))); - state = PA_CONTEXT_FAILED; + /* Treat as a connection failure */ + state = PA_CONTEXT_FAILED; + } } if (state == PA_CONTEXT_TERMINATED || state == PA_CONTEXT_FAILED) { @@ -1181,6 +1244,9 @@ connection_change_state (PulseConnection *connection, PulseConnectionState state static void connection_list_loaded (PulseConnection *connection) { + /* Decrement the number of outstanding requests as a list has just been + * downloaded; when the number reaches 0, server information is requested + * as the final step in the connection process */ connection->priv->outstanding--; if (G_UNLIKELY (connection->priv->outstanding < 0)) { -- cgit v1.2.1