// // banshee-player-missing-elements.c // // Author: // Aaron Bockover // Julien Moutte // // Copyright (C) 2005-2008 Novell, Inc. // Copyright (C) 2010 Fluendo S.A. // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #include "banshee-player-missing-elements.h" // --------------------------------------------------------------------------- // Private Functions // --------------------------------------------------------------------------- static gchar ** bp_slist_to_ptr_array (const GSList *elements) { GPtrArray *vector = g_ptr_array_new (); while (elements != NULL) { g_ptr_array_add (vector, g_strdup (elements->data)); elements = elements->next; } g_ptr_array_add (vector, NULL); return (gchar **)g_ptr_array_free (vector, FALSE); } static void bp_slist_destroy (GSList *list) { GSList *node = list; if (node == NULL) { return; } for (; node != NULL; node = node->next) { g_free (node->data); } g_slist_free (list); } static void bp_missing_elements_handle_install_failed (BansheePlayer *player) { g_return_if_fail (IS_BANSHEE_PLAYER (player)); bp_slist_destroy (player->missing_element_details); player->missing_element_details = NULL; if (GST_IS_ELEMENT (player->playbin)) { gst_element_set_state (player->playbin, GST_STATE_READY); } if (player->error_cb != NULL) { player->error_cb (player, GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, NULL, NULL); } } static void bp_missing_elements_handle_install_result (GstInstallPluginsReturn result, gpointer data) { BansheePlayer *player = (BansheePlayer *)data; g_return_if_fail (IS_BANSHEE_PLAYER (player)); // TODO: Actually handle a successful plugin installation // if (result == GST_INSTALL_PLUGINS_SUCCESS) { // } bp_missing_elements_handle_install_failed (player); gst_install_plugins_context_free (player->install_plugins_context); player->install_plugins_context = NULL; } // --------------------------------------------------------------------------- // Internal Functions // --------------------------------------------------------------------------- void _bp_missing_elements_destroy (BansheePlayer *player) { g_return_if_fail (IS_BANSHEE_PLAYER (player)); bp_slist_destroy (player->missing_element_details); bp_slist_destroy (player->missing_element_details_handled); if (player->install_plugins_context != NULL) { gst_install_plugins_context_free (player->install_plugins_context); } } void _bp_missing_elements_process_message (BansheePlayer *player, GstMessage *message) { g_return_if_fail (IS_BANSHEE_PLAYER (player)); g_return_if_fail (message != NULL); if (gst_is_missing_plugin_message (message)) { gchar *detail = gst_missing_plugin_message_get_installer_detail (message); GSList *node = player->missing_element_details_handled; player->handle_missing_elements = TRUE; // Only save the error if we've never encounted it before for (; node != NULL; node = node->next) { if (g_ascii_strcasecmp (node->data, detail) == 0) { bp_debug2 ("Ignoring missing element details, already prompted ('%s')", detail); return; } } bp_debug2 ("Saving missing element details ('%s')", detail); player->missing_element_details = g_slist_append (player->missing_element_details, detail); } } void _bp_missing_elements_handle_state_changed (BansheePlayer *player, GstState old, GstState new) { GstInstallPluginsReturn install_return; gchar **details; GSList *node; g_return_if_fail (IS_BANSHEE_PLAYER (player)); if (old != GST_STATE_READY || new != GST_STATE_PAUSED || !player->handle_missing_elements || player->install_plugins_context != NULL) { return; } else if (player->missing_element_details == NULL) { bp_debug ("Ignoring missing elements, nothing new to handle"); player->handle_missing_elements = FALSE; bp_missing_elements_handle_install_failed (player); return; } bp_debug ("Handling missing elements"); details = bp_slist_to_ptr_array (player->missing_element_details); player->install_plugins_context = gst_install_plugins_context_new (); #ifdef GDK_WINDOWING_X11 if (player->window != NULL) { gst_install_plugins_context_set_xid (player->install_plugins_context, GDK_WINDOW_XWINDOW (player->window)); } #endif install_return = gst_install_plugins_async ((const gchar * const*) details, player->install_plugins_context, bp_missing_elements_handle_install_result, player); if (install_return != GST_INSTALL_PLUGINS_STARTED_OK) { bp_missing_elements_handle_install_failed (player); gst_install_plugins_context_free (player->install_plugins_context); player->install_plugins_context = NULL; } g_strfreev (details); // Move all the missing element details from the current list to a cached // list so we don't show the same missing elements message twice in an instance bp_debug ("Saving missing elements so we don't bother you again"); for (node = player->missing_element_details; node != NULL; node = node->next) { player->missing_element_details_handled = g_slist_append ( player->missing_element_details_handled, node->data); } g_slist_free (player->missing_element_details); player->missing_element_details = NULL; player->handle_missing_elements = FALSE; }