title: Python Gstreamer 1.0 Frozen into a standalone app - Is it possible?
body: <p>I've been struggling with trying to get the Python GStreamer 1.0 bindings running standalone in it's own executable.   It turns out it's a lot more complicated than I was expecting and very little documentation out there for it.  So I'm going to run through what worked for me and hopefully people can add what could be improved onto this approach...</p>
  
  <p>I first attempted to compile it with PyInstaller with the appeal that I could get it down to just one exe file however after days of struggling I discovered that the GTK+3 which is what GStreamer 1.0 is running with uses Namespace Packages which is only currently supported with cx_Freeze. (eventually also with PyInstaller 3.0 apparently)</p>
  
  <p>That was the big issue but there are other modifications that needed to be made to get it working in a self contained program.</p>
  
  <p>Running:</p>
  
  <ul>
  <li><p>gstreamer-1.0-devel-x86-1.2.3</p></li>
  <li><p>pygi-aio-3.10.2-win32_rev16 (Creates the gnome folders and adds gstreamer dll's when specified in the installer)</p></li>
  </ul>
  
  <p>Here is what I ended up with as a cx_freeze setup file running with 'bdist_msi' flag:</p>
  
  <pre><code>################################
  ######### CX-FREEZE ############
  ################################
  import os, site, sys
  from cx_Freeze import setup, Executable
  
  include_files = []
  import site
  include_dll_path = site.getsitepackages()[-1]
  
  ###### FINDING Gstreamer FILES TO BE INCLUDED ######
  ## Collect the list of missing dll when cx_freeze builds the app
  
  gnomePath = os.path.join(include_dll_path, "gnome")
  for fileName in os.listdir(gnomePath): 
      fullname = os.path.join(gnomePath, fileName) 
      if os.path.isfile(fullname): 
          include_files.append((fullname, fileName))
  
  ## We need to add all the libraries too (for themes, etc..)
  gtk_libs = ['lib']
  for lib in gtk_libs:
      include_files.append((os.path.join(include_dll_path, "gnome", lib), lib))
  
  base = None
  
  ## Lets not open the console while running the app
  if sys.platform == "win32":
      base = "Win32GUI"
  
  executables = [
      Executable(
                  "test.py",
                  #base=base,
                  base="Console",
                  targetName = 'test.exe',
                  shortcutName="test Player",
                  shortcutDir="DesktopFolder",
      )
  ]
  
  buildOptions = dict(
      compressed = False,
      includes = ['gi._glib'],
      excludes = [],
      packages = [],
      silent=False,
      include_files = include_files,
      icon = 'test.ico',
      namespace_packages = 'gi.overrides',
      copy_dependent_files = True
      )
  
  setup(
      name = "Test",
      author = "Simon Warwick",
      version = "0.0.0",
      description = "Test Player",
      options = dict(build_exe = buildOptions),
      executables = executables
  )
  </code></pre>
  
  <p>Some of the other issues I ran across:</p>
  
  <ol>
  <li><p>Gnome main dll's need to go to the root of the install package</p></li>
  <li><p>Gnome Library files (gstreamer-1.0 DLLs and girepository-1.0 typelibs) need to sit relative inside the install package</p></li>
  <li><p>Specific include of gi._glib is required</p></li>
  <li><p>Within the Gstreamer python scripts any filepath within 'filesrc' has to be passed as a string only when the app is frozen (as opposed
  to unicode)</p></li>
  <li><p>Using 'get_property' attribute to retrieve gstreamer object data (like using 'location' with filesrc) mysteriously switches to
  requiring 3 arguments when frozen so the workaround I luckily found
  was to use get_properties() and pulling the first value from it's
  list.</p></li>
  </ol>
  
  <p>That's as much as I can remember at the moment but I'll update the list if I learn about more.</p>