Problems list for porting Jokosher from GTK+2/PyGTK to GTK+3/PyGI

This is working list of problems for my Google Summer of Code project to port Jokosher (which is fairly classic GTK+2/PyGTK application) to Gtk+3 using Python Gobject Introspection. More about GObject Introspection read here.

Problem #1

See Jokosher/JokosherApp.py, line 2054

Solution: Problem with GtkTextBuffer.get_text function - now it requires additional Boolean value for including hidden text. Had to take get_bounds out of params because it otherwise didn't allow Boolean to follow.

Status: SOLVED

Problem #2

(jokosher:1971): Gtk-WARNING **: Unknown property: GtkDialog.has-separator
Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/AddInstrumentDialog.py", line 111, in OnSelected
    self.OnOK()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/AddInstrumentDialog.py", line 127, in OnOK
    item = self.model[i[0]]
TypeError: 'TreePath' object does not support indexing

Solution: it is a GtkIconView, get_selected_items method now returns !GList with GtkTreePath. API can be found here: http://developer.gnome.org/gtk3/3.0/GtkTreeModel.html#GtkTreePath-struct We use GtkTreePath.to_string() method to extract selected value from GtkTreePath (which is counted by value of i)

Status: SOLVED

Problem #3 - Problems with Unicode symbols

[(u'Akustisk\u0101 \u0123it\u0101ra', 'acousticguitar')]
Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/AddInstrumentDialog.py", line 111, in OnSelected
    self.OnOK()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/AddInstrumentDialog.py", line 135, in OnOK
    self.project.AddInstruments(instrList)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Project.py", line 1190, in AddInstruments
    instr = self.AddInstrument(name, type, _undoAction_=undoAction)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/UndoSystem.py", line 95, in UndoWrapper
    project.SaveIncrementalAction(inc)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Project.py", line 867, in SaveIncrementalAction
    incr_file.write(action.StoreToString())
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/IncrementalSave.py", line 178, in StoreToString
    self.WriteToXMLAttributes(None, arg, node)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/IncrementalSave.py", line 195, in WriteToXMLAttributes
    Utils.StoreVariableToNode(value, node, "type", "value")
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Utils.py", line 380, in StoreVariableToNode
    node.setAttribute(valueAttr, str(value))
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0101' in position 8: ordinal not in range(128)

Solution: Not sure if it's jhbuild problem, or something I can fix within Jokosher.

Status: NEED MORE INFORMATION

Problem #4 - Gdk drawable methods replaced by Cairo context drawing

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/EventLaneViewer.py", line 152, in OnDraw
    gc = wnd.new_gc()
AttributeError: 'gtk.gdk.X11Window' object has no attribute 'new_gc'

Solution: replace GDK methods with Cairo ones, using pycairo.

Notes: Old method
http://developer.gnome.org/gdk/stable/gdk-Drawing-Primitives.html#gdk-draw-line
New method
http://cairographics.org/manual/cairo-Paths.html#cairo-line-to
http://zetcode.com/tutorials/cairographicstutorial/basicdrawing/

Status: SOLVED

Problem #5

(jokosher:2646): Gtk-WARNING **: Unknown property: GtkDialog.has-separator

Solution: Problem within "Project Properties" dialog .ui file, which has has_separator attribute enabled, which are removed in 3.0. It gives separator between form stuff and buttons. Not sure what replaces it in 3.0.

Status: NEED MORE INFORMATION

Problem #6

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/pyintrospection-gtk3/Jokosher/InstrumentViewer.py", line 324, in OnInstrumentSelected
    self.modify_bg(Gtk.StateType.NORMAL, self.SELECTED_COLOUR)
  File "/opt/gnome/lib/python2.6/site-packages/gi/types.py", line 44, in function
    return info.invoke(*args)
TypeError: argument 2: Must be Gdk.Color, not RGBA

Solution: replace modify_bg with override_background_color()

Status: SOLVED

Problem #7

GLib-GIO-Message: Using the 'memory' GSettings backend.  Your settings will not be saved or shared with other applications.

Solution: Could not reproduce, but will have to look at Gconf replacement stuff anyway later.

Status: NEED MORE INFORMATION

Problem #8

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/pyintrospection-gtk3/Jokosher/InstrumentViewer.py", line 224, in OnEditLabel
    width = self.labeleventbox.size_request()[0]
TypeError: 'Requisition' object does not support indexing

Solution: change size_request to get_preffered_size(). It retuns two GtkRequisition objects, which in turn has 'width' and 'height' attributes. So for example to get minimal size of widget, get_preffered_size()[0].width minimal size is first GtkRequisition of tulpe

Status: SOLVED

Notes: Fixing this I encountered strange error which causes every GtkWdiget to be double in width with my current jbhuild setup.

Problem #9

File "/home/peteris/Dokumenti/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 745, in OnPreferences
    prefsdlg = PreferencesDialog.PreferencesDialog(self.project, self, self.icon)
  File "/home/peteris/Dokumenti/pyintrospection-gtk3/Jokosher/PreferencesDialog.py", line 75, in __init__
    self.recordingSoundSystem.append_text(_("Custom"))

Solution: GtkComboBox is replaced by GtkComboBoxText and remove GtkRenderCellText because Gtk will create one when adding text entries.

Status: SOLVED

Problem #10

File "/home/peteris/Dokumenti/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 410, in About
    Gtk.AboutDialog.set_website(self.AboutLinkActivate)
TypeError: unbound method set_website() must be called with AboutDialog instance as first argument (got instancemethod instance instead)

Solution: Use new_with_model() to initialise GtkComboBox properly.

Status: SOLVED

Notes: solved with applying set_website and set_website_label on GtkAboutDialog object. not fully sure this is right way.

Problem #11

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 1502, in OnInstrumentConnectionsDialog
    InstrumentConnectionsDialog.InstrumentConnectionsDialog(self.project, self)
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentConnectionsDialog.py", line 54, in __init__
    self.Populate()
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentConnectionsDialog.py", line 126, in Populate
    combobox = Gtk.ComboBox(liststore)
TypeError: GObject.__init__() takes exactly 0 arguments (1 given)

Solution: Use new_with_model() to initialise GtkComboBox properly.

Status: SOLVED

Problem #12

/usr/lib/gstreamer0.10/gstreamer-0.10/gst-plugin-scanner: /opt/gnome/lib/libxml2.so.2: no version information available (required by /usr/lib/libgstreamer-0.10.so.0)
** Message: pygobject_register_sinkfunc is deprecated (GstObject)
Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/ControlsBox.py", line 217, in OnEffectsButtonClicked
    self.mainview.icon)
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 52, in __init__
    self.gtk_builder = Globals.LoadGtkBuilderFilename("InstrumentEffectsDialog.ui")
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/Globals.py", line 371, in LoadGtkBuilderFilename
    builder.add_from_file(os.path.join(GTK_BUILDER_PATH, filename))
  File "/opt/gnome/lib/python2.6/site-packages/gi/types.py", line 44, in function
    return info.invoke(*args)
glib.GError: Invalid object type `GtkComboBoxEntry'

Solution: Change GtkComboBoxEntry to GtkComboBoxText with has-entry enabled. Remove GtkRenderCellText too.

Status: SOLVED

Problem #13

Traceback (most recent call last):
  File "/opt/gnome/lib/python2.6/site-packages/gi/overrides/Gtk.py", line 298, in _full_callback
    raise AttributeError('Handler %s not found' % handler_name)
AttributeError: Handler on_listActiveEffects_selected not found
Traceback (most recent call last):
  File "/opt/gnome/lib/python2.6/site-packages/gi/overrides/Gtk.py", line 298, in _full_callback
    raise AttributeError('Handler %s not found' % handler_name)
AttributeError: Handler on_listEffects_selected not found

Solution: This is not a porting bug, this is undefined handler for signal. Defering it for solving later.

Status: NEED MORE INFORMATION

Problem #14

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/ControlsBox.py", line 217, in OnEffectsButtonClicked
    self.mainview.icon)
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 131, in __init__
    self.filterEffects = self.modelEffects.filter_new()
  File "/opt/gnome/lib/python2.6/site-packages/gi/types.py", line 44, in function
    return info.invoke(*args)
TypeError: filter_new() takes exactly 2 argument(s) (1 given)

Solution: filter_new() which is GtkTreeModelFilter method requires additional argument of GtkTreePath root. Set to None fixed it.

Status: SOLVED

Problem #15

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 308, in OnClose
    self.instrument.project.disconnect_by_func(self.OnProjectPlay)
TypeError: nothing connected to <bound method InstrumentEffectsDialog.OnProjectPlay of <InstrumentEffectsDialog.InstrumentEffectsDialog instance at 0x945856c>>
Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 1047, in OnDestroy
    Globals.settings.general["instrumenteffectwindowwidth"] = self.width
AttributeError: InstrumentEffectsDialog instance has no attribute 'width'

Solution: Happened in combination with another bug, but can't reproduce it anymore. InstrumentEffectsDialog has this attribute defined properly.

Status: CAN'T REPRODUCE

Problem #16 - GtkTreePath syntax changed, doesn't support indexing

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 639, in OnEffectSettings
    self.effectpos = self.modelActiveEffects[selection[1]].path[0]
TypeError: 'TreePath' object does not support indexing

Solution: Use path.get_indices() to get list of ints for selected object indexes (GtkTreePath).

Status: SOLVED

Problem #17

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 653, in OnEffectSettings
    self.settings_gtk_builder = Globals.LoadGtkBuilderFilename("EffectSettingsDialog.ui")
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/Globals.py", line 371, in LoadGtkBuilderFilename
    builder.add_from_file(os.path.join(GTK_BUILDER_PATH, filename))
  File "/opt/gnome/lib/python2.6/site-packages/gi/types.py", line 44, in function
    return info.invoke(*args)
glib.GError: Invalid object type `GtkComboBoxEntry'

Solution: Similar to previous problems, change GtkComboBoxEntry to GtkComboBoxText with has-entry enabled. Remove GtkRenderCellText too.

Status: SOLVED

Problem #18 - GtkHScale should be initialised with new() method

File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 741, in OnEffectSettings
    self.sliderdict[property.name] = hscale = Gtk.HScale(adj)
TypeError: GObject.__init__() takes exactly 0 arguments (1 given)

Solution: !HScale should created properly by method new(GtkAdjustment).

Status: SOLVED

Problem #19 - Another path[0] cases

Changed path[0] to path.get_indices()[0] in OnEffectDeleted, OnEffectUp, OnEffectDown too.

Status: SOLVED

Problem #20 - using set_cursor()

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrāde/pyintrospection-gtk3/Jokosher/InstrumentEffectsDialog.py", line 622, in OnEffectDeleted
    self.listActiveEffects.set_cursor(None, None, False)
  File "/opt/gnome/lib/python2.6/site-packages/gi/types.py", line 44, in function
    return info.invoke(*args)
TypeError: argument 1: Must be Gtk.TreePath, not NoneType
Method must get three arguments, and first of them must be TreePath object (other two can be None and False).

Solution: set_cursor must have three params, and first one should be GtkTreePath. Must understand which one I should set to.

Status: UNRESOLVED

Problem #21 - Waveform drawing doesn't work

Waveform drawing doesn't work and event doesn't get created. I don't get any errors or warnings. It seems that I need to convert pygst to Gst/GI for it to work properly.

Status: UNRESOLVED

Problem #22 - GtkMenu.popup() requires additional param

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/EventLaneViewer.py", line 231, in OnMouseDown
    self.contextMenu.popup(None, None, None, mouse.button, mouse.time)
TypeError: popup() takes exactly 7 arguments (6 given)

Solution: provide additional parameter for method, which is data for function which is passed as third parameter, For more see http://developer.gnome.org/gtk3/stable/GtkMenu.html#gtk-menu-popup

Status: SOLVED

Problem #23 - "import gst" and similar strings must be change to "from gi.repository import Gst", also "gst." must be changed to "Gst."

Solution: Grep for import clauses, and use customised script to replace gst. with Gst.

Status: SOLVED

Problem #24 - GtkMenu.popup() requires additional param

Traceback (most recent call last):
  File "Jokosher/Jokosher", line 106, in <module>
    JokosherApp.MainApp(openproject, loadExtensions, startupType)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 260, in __init__
    self.CheckGstreamerVersions()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 1672, in CheckGstreamerVersions
    gnl = Gst.registry_get_default().find_plugin("gnonlin")
  File "/data/opt/gnome/lib/python2.7/site-packages/gi/module.py", line 274, in __getattr__
    return getattr(self._introspection_module, name)
  File "/data/opt/gnome/lib/python2.7/site-packages/gi/module.py", line 105, in __getattr__
    self.__name__, name))
AttributeError: 'gi.repository.Gst' object has no attribute 'registry_get_default'

Solution: use Gst.Registry.get_default() method. This repeats several times in next lines in the code.

Status: SOLVED

Problem #25 - Empty plugin list

Solution: when using GObject Introspetion and Gstreamer, you must initialise Gstreamer with Gst.init(None), where None in this case is list of params passed to it (t.i. we pass nothing).

Status: SOLVED

Problem #26 - Gstreamer error exceptions doesn't work

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 883, in OnNewProject
    project = ProjectManager.CreateNewProject(name, author)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 41, in CreateNewProject
    project = InitProjectLocation(projecturi)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 79, in InitProjectLocation
    except Gst.PluginNotFoundError, e:
NameError: global name 'Gst' is not defined

Solution: although annotations specification mentions availability to define throwing exceptions in case of error (http://live.gnome.org/GObjectIntrospection/Annotations), it isn't implemented in GObject Introspection yet, therefore it is not fixable at this point.

Status: SOLVED

Problem #27 - wrong parent defined when constructing object

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 899, in OnNewProject
    dlg = Gtk.MessageDialog(self.dlg,
AttributeError: MainApp instance has no attribute 'dlg'

Solution: Change self.dlg to self.window, as it is rightful parent of message dialog window.

Status: SOLVED

Problem #28 - use right constructor for Gst.Pipeline object

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 883, in OnNewProject
    project = ProjectManager.CreateNewProject(name, author)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 41, in CreateNewProject
    project = InitProjectLocation(projecturi)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 77, in InitProjectLocation
    project = Project.Project()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Project.py", line 144, in __init__
    self.mainpipeline = Gst.Pipeline("timeline")
TypeError: GObject.__init__() takes exactly 0 arguments (1 given)

Solution: use Gst.Pipeline.new() method (constructor).

Status: SOLVED

Problem #28 - use right constructor for Gst.Bin object

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 883, in OnNewProject
    project = ProjectManager.CreateNewProject(name, author)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 41, in CreateNewProject
    project = InitProjectLocation(projecturi)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 77, in InitProjectLocation
    project = Project.Project()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Project.py", line 145, in __init__
    self.playbackbin = Gst.Bin("playbackbin")
TypeError: GObject.__init__() takes exactly 0 arguments (1 given)

Solution: use Gst.Bin.new() method (constructor).

Status: SOLVED

Problem #29 - where to find and how to use gst_parse_bin_from_description

Traceback (most recent call last):
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/JokosherApp.py", line 883, in OnNewProject
    project = ProjectManager.CreateNewProject(name, author)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 41, in CreateNewProject
    project = InitProjectLocation(projecturi)
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/ProjectManager.py", line 77, in InitProjectLocation
    project = Project.Project()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Project.py", line 149, in __init__
    self.masterSink = self.MakeProjectSink()
  File "/home/peteris/Dokumenti/Izstrade/pyintrospection-gtk3/Jokosher/Project.py", line 1609, in MakeProjectSink
    sinkBin = Gst.Parse().bin_from_description(sinkString, True)
  File "/data/opt/gnome/lib/python2.7/site-packages/gi/module.py", line 274, in __getattr__
    return getattr(self._introspection_module, name)
  File "/data/opt/gnome/lib/python2.7/site-packages/gi/module.py", line 105, in __getattr__
    self.__name__, name))
AttributeError: 'gi.repository.Gst' object has no attribute 'Parse'

Solution: use Gst.parse_bin_from_description() method. Parse as object isn't exported to annotations (and propably won't be).

Status: SOLVED

Problem #30 - how to use Gst.Iterator.next() method

Solution: Previously using Gstreamer python bindings you never came into contact with iterator objects. In Gst/GI it's the only way to get sinks from bin. Therefore, to access this list (when getting it with Gst.Bin.iterate_sinks()), you must use next() method now on Gst.Iterator as returned value, which will step by step give you sinks of the mentioned bin. However, next() method is not usable without changing it's syntax, because it returns GstIteratorResult and passes actual return value to pointer which is only param of the method. As Python doesn't allow such syntax, I use (out caller-allocates) annotation for this param and use this method in this way:

return_result, return_value = Gst.Iterator.next()

P.S.: problem was reported, patch provided and fixed in Gstreamer 0.11 branch http://cgit.freedesktop.org/gstreamer/gstreamer/commit/?h=0.11&id=59bf122584a6c33db99ba4da1851aab09092d61a

Status: SOLVED

Problem #31 - How to use Gst.ElementFactory.make()

Solution: Use Gst.ElementFactory.make() method instead of gst.element_factory_make(). Also pass second argument as name (or None if you want Gstreamer to assign name itself).

Status: SOLVED

Problem #32 - Problem with GObject Introspection and floating reference GObject (GInitiallyUnowned)

Solution: Short recap of the problem - In 0.11 series Gstreamer starts to use Glib floating reference support. In 0.10 series Gstreamer GI support worked with (transfer full) for floating ref objects as returned values (for not fully understood reasons, but 0.10 used it's own float ref object system), but in 0.11 this resulted in segfault. Someone must use (transfer none) to get floating ref object as return value. After receiving object, it is sinked with ref_sink() in bindings (for example, in pygobject or gjs). and floating reference is converted to common one, with binding as owner of it. Mind you it is temporary solution as Gstreamer and GI devs look for more elegant solution. For more read here https://bugzilla.gnome.org/show_bug.cgi?id=656205

Status: TEMP. SOLVED

Attic/BugListJokosherGSoC2011 (last edited 2013-12-03 18:54:45 by WilliamJonMcCann)