element: Enforce that elements created by gst_element_factory_create/make() are floating
[platform/upstream/gstreamer.git] / gst / gstpluginloader.c
index 6ac9b60..a933a4b 100644 (file)
@@ -16,8 +16,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <fcntl.h>
 #include <unistd.h>
 #else
+#define WIN32_LEAN_AND_MEAN
+
 #define fsync(fd) _commit(fd)
 #include <io.h>
+
+#include <windows.h>
+extern HMODULE _priv_gst_dll_handle;
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
 #endif
 
 #include <errno.h>
@@ -330,12 +339,12 @@ static void
 plugin_loader_create_blacklist_plugin (GstPluginLoader * l,
     PendingPluginEntry * entry)
 {
-  GstPlugin *plugin = g_object_newv (GST_TYPE_PLUGIN, 0, NULL);
+  GstPlugin *plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
 
   plugin->filename = g_strdup (entry->filename);
   plugin->file_mtime = entry->file_mtime;
   plugin->file_size = entry->file_size;
-  plugin->flags |= GST_PLUGIN_FLAG_BLACKLISTED;
+  GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED);
 
   plugin->basename = g_path_get_basename (plugin->filename);
   plugin->desc.name = g_intern_string (plugin->basename);
@@ -350,39 +359,76 @@ plugin_loader_create_blacklist_plugin (GstPluginLoader * l,
   gst_registry_add_plugin (l->registry, plugin);
 }
 
-static gboolean
-gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location)
-{
 #ifdef __APPLE__
 #if defined(__x86_64__)
-  char *argv[] = { (char *) "/usr/bin/arch", (char *) "-x86_64",
-    location, (char *) "-l", NULL
-  };
+#define USR_BIN_ARCH_SWITCH "-x86_64"
 #elif defined(__i386__)
-  char *argv[] = { (char *) "/usr/bin/arch", (char *) "-i386",
-    location, (char *) "-l", NULL
-  };
+#define USR_BIN_ARCH_SWITCH "-i386"
 #elif defined(__ppc__)
-  char *argv[] = { (char *) "/usr/bin/arch", (char *) "-ppc",
-    location, (char *) "-l", NULL
-  };
+#define USR_BIN_ARCH_SWITCH "-ppc"
 #elif defined(__ppc64__)
-  char *argv[] = { (char *) "/usr/bin/arch", (char *) "-ppc64",
-    location, (char *) "-l", NULL
-  };
+#define USR_BIN_ARCH_SWITCH "-ppc64"
 #endif
-#else /* ! __APPLE__ */
-  char *argv[] = { location, (char *) "-l", NULL };
 #endif
 
+#define YES_MULTIARCH 1
+#define NO_MULTIARCH  2
 
-#ifdef __APPLE__
-  GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s",
-      location, argv[1]);
-#else
-  GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location);
+#if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH)
+static gboolean
+gst_plugin_loader_use_usr_bin_arch (void)
+{
+  static volatile gsize multiarch = 0;
+
+  if (g_once_init_enter (&multiarch)) {
+    gsize res = NO_MULTIARCH;
+
+#ifdef HAVE_SYS_UTSNAME_H
+    {
+      struct utsname uname_data;
+
+      if (uname (&uname_data) == 0) {
+        /* Check for OS X >= 10.5 (darwin kernel 9.0) */
+        GST_LOG ("%s %s", uname_data.sysname, uname_data.release);
+        if (g_ascii_strcasecmp (uname_data.sysname, "Darwin") == 0 &&
+            g_strtod (uname_data.release, NULL) >= 9.0) {
+          res = YES_MULTIARCH;
+        }
+      }
+    }
 #endif
 
+    GST_INFO ("multiarch: %s", (res == YES_MULTIARCH) ? "yes" : "no");
+    g_once_init_leave (&multiarch, res);
+  }
+  return (multiarch == YES_MULTIARCH);
+}
+#endif /* __APPLE__ && USR_BIN_ARCH_SWITCH */
+
+static gboolean
+gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location)
+{
+  char *argv[6] = { NULL, };
+  int c = 0;
+
+#if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH)
+  if (gst_plugin_loader_use_usr_bin_arch ()) {
+    argv[c++] = (char *) "/usr/bin/arch";
+    argv[c++] = (char *) USR_BIN_ARCH_SWITCH;
+  }
+#endif
+  argv[c++] = location;
+  argv[c++] = (char *) "-l";
+  argv[c++] = _gst_executable_path;
+  argv[c++] = NULL;
+
+  if (c > 4) {
+    GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s",
+        location, argv[1]);
+  } else {
+    GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location);
+  }
+
   if (!g_spawn_async_with_pipes (NULL, argv, NULL,
           G_SPAWN_DO_NOT_REAP_CHILD /* | G_SPAWN_STDERR_TO_DEV_NULL */ ,
           NULL, NULL, &loader->child_pid, &loader->fd_w.fd, &loader->fd_r.fd,
@@ -417,7 +463,9 @@ gst_plugin_loader_spawn (GstPluginLoader * loader)
 
   /* Find the gst-plugin-scanner: first try the env-var if it is set,
    * otherwise use the installed version */
-  env = g_getenv ("GST_PLUGIN_SCANNER");
+  env = g_getenv ("GST_PLUGIN_SCANNER_1_0");
+  if (env == NULL)
+    env = g_getenv ("GST_PLUGIN_SCANNER");
 
   if (env != NULL && *env != '\0') {
     GST_LOG ("Trying GST_PLUGIN_SCANNER env var: %s", env);
@@ -428,7 +476,22 @@ gst_plugin_loader_spawn (GstPluginLoader * loader)
 
   if (!res) {
     GST_LOG ("Trying installed plugin scanner");
+
+#ifdef G_OS_WIN32
+    {
+      gchar *basedir;
+
+      basedir =
+          g_win32_get_package_installation_directory_of_module
+          (_priv_gst_dll_handle);
+      helper_bin =
+          g_build_filename (basedir, GST_PLUGIN_SCANNER_SUBDIR,
+          "gstreamer-" GST_API_VERSION, "gst-plugin-scanner.exe", NULL);
+      g_free (basedir);
+    }
+#else
     helper_bin = g_strdup (GST_PLUGIN_SCANNER_INSTALLED);
+#endif
     res = gst_plugin_loader_try_helper (loader, helper_bin);
     g_free (helper_bin);
 
@@ -466,6 +529,7 @@ plugin_loader_cleanup_child (GstPluginLoader * l)
 gboolean
 _gst_plugin_loader_client_run (void)
 {
+  gboolean res = TRUE;
   GstPluginLoader *l;
 
   l = plugin_loader_new (NULL);
@@ -481,16 +545,18 @@ _gst_plugin_loader_client_run (void)
 
     dup_fd = dup (0);           /* STDIN */
     if (dup_fd == -1) {
-      GST_ERROR ("Failed to start. Could no dup STDIN, errno %d", errno);
-      return FALSE;
+      GST_ERROR ("Failed to start. Could not dup STDIN, errno %d", errno);
+      res = FALSE;
+      goto beach;
     }
     l->fd_r.fd = dup_fd;
     close (0);
 
     dup_fd = dup (1);           /* STDOUT */
     if (dup_fd == -1) {
-      GST_ERROR ("Failed to start. Could no dup STDOUT, errno %d", errno);
-      return FALSE;
+      GST_ERROR ("Failed to start. Could not dup STDOUT, errno %d", errno);
+      res = FALSE;
+      goto beach;
     }
     l->fd_w.fd = dup_fd;
     close (1);
@@ -516,9 +582,13 @@ _gst_plugin_loader_client_run (void)
   /* Loop, listening for incoming packets on the fd and writing responses */
   while (!l->rx_done && exchange_packets (l));
 
+#ifndef G_OS_WIN32
+beach:
+#endif
+
   plugin_loader_free (l);
 
-  return TRUE;
+  return res;
 }
 
 static void
@@ -544,7 +614,8 @@ put_packet (GstPluginLoader * l, guint type, guint32 tag,
   /* 4 bytes packet length */
   GST_WRITE_UINT32_BE (out + 4, payload_len);
   /* payload */
-  memcpy (out + HEADER_SIZE, payload, payload_len);
+  if (payload && payload_len)
+    memcpy (out + HEADER_SIZE, payload, payload_len);
   /* Write magic into the header */
   GST_WRITE_UINT32_BE (out + 8, HEADER_MAGIC);
 
@@ -661,7 +732,7 @@ do_plugin_load (GstPluginLoader * l, const gchar * filename, guint tag)
 
     /* Now serialise the plugin details and send */
     if (!_priv_gst_registry_chunks_save_plugin (&chunks,
-            gst_registry_get_default (), newplugin))
+            gst_registry_get (), newplugin))
       goto fail;
 
     /* Store where the header is, write an empty one, then write
@@ -809,7 +880,7 @@ handle_rx_packet (GstPluginLoader * l,
           return FALSE;
         }
 
-        newplugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
+        GST_OBJECT_FLAG_UNSET (newplugin, GST_PLUGIN_FLAG_CACHED);
         GST_LOG_OBJECT (l->registry,
             "marking plugin %p as registered as %s", newplugin,
             newplugin->filename);
@@ -954,27 +1025,31 @@ exchange_packets (GstPluginLoader * l)
         l->tx_buf_write - l->tx_buf_read);
 
     if (!l->rx_done) {
-      if (gst_poll_fd_has_error (l->fdset, &l->fd_r) ||
-          gst_poll_fd_has_closed (l->fdset, &l->fd_r)) {
-        GST_LOG ("read fd %d closed/errored", l->fd_r.fd);
+      if (gst_poll_fd_has_error (l->fdset, &l->fd_r)) {
+        GST_LOG ("read fd %d errored", l->fd_r.fd);
         goto fail_and_cleanup;
       }
 
       if (gst_poll_fd_can_read (l->fdset, &l->fd_r)) {
         if (!read_one (l))
           goto fail_and_cleanup;
+      } else if (gst_poll_fd_has_closed (l->fdset, &l->fd_r)) {
+        GST_LOG ("read fd %d closed", l->fd_r.fd);
+        goto fail_and_cleanup;
       }
     }
 
     if (l->tx_buf_read < l->tx_buf_write) {
-      if (gst_poll_fd_has_error (l->fdset, &l->fd_w) ||
-          gst_poll_fd_has_closed (l->fdset, &l->fd_r)) {
-        GST_ERROR ("write fd %d closed/errored", l->fd_w.fd);
+      if (gst_poll_fd_has_error (l->fdset, &l->fd_w)) {
+        GST_ERROR ("write fd %d errored", l->fd_w.fd);
         goto fail_and_cleanup;
       }
       if (gst_poll_fd_can_write (l->fdset, &l->fd_w)) {
         if (!write_one (l))
           goto fail_and_cleanup;
+      } else if (gst_poll_fd_has_closed (l->fdset, &l->fd_w)) {
+        GST_LOG ("write fd %d closed", l->fd_w.fd);
+        goto fail_and_cleanup;
       }
     }
   } while (l->tx_buf_read < l->tx_buf_write);