def set_value(self, field, value): """Set a named item on an Image. Values are converted from Python types to something libvips can swallow. For example, bytes() can be used to set VipsBlob fields. """ gtype = self.get_typeof(field) logger.debug('%s.%s = %s' % (self, field, value)) logger.debug('%s.%s needs a %s' % (self, field, gtype)) # if there's a thing of this name already, convert to that type if gtype != GObject.TYPE_INVALID: # blob-ize if GObject.type_is_a(gtype, vips_type_blob): if not isinstance(value, Vips.Blob): value = Vips.Blob.new(None, value) # image-ize if GObject.type_is_a(gtype, vips_type_image): if not isinstance(value, Vips.Image): value = imageize(self, value) # array-ize some types, if necessary value = arrayize(gtype, value) self.set(field, value)
def set_value(self, match_image, value): logger.debug('assigning %s to %s' % (value, self.name)) logger.debug('%s needs a %s' % (self.name, self.prop.value_type)) # blob-ize if GObject.type_is_a(self.prop.value_type, vips_type_blob): if not isinstance(value, Vips.Blob): value = Vips.Blob.new(None, value) # image-ize if GObject.type_is_a(self.prop.value_type, vips_type_image): if not isinstance(value, Vips.Image): value = imageize(match_image, value) # array-ize some types, if necessary value = arrayize(self.prop.value_type, value) # MODIFY input images need to be copied before assigning them if self.flags & Vips.ArgumentFlags.MODIFY: # don't use .copy(): we want to make a new pipeline with no # reference back to the old stuff ... this way we can free the # previous image earlier logger.debug('MODIFY argument: copying image') new_image = Vips.Image.new_memory() value.write(new_image) value = new_image logger.debug('assigning %s' % value) self.op.props.__setattr__(self.name, value)
def get_prop_type(setting, pspec, propxml): dbus_type = setting.get_dbus_property_type(pspec.name).dup_string() prop_type = dbus_type_name_map[dbus_type] if GObject.type_is_a(pspec.value_type, GObject.TYPE_ENUM) or GObject.type_is_a(pspec.value_type, GObject.TYPE_FLAGS): prop_type = "%s (%s)" % (pspec.value_type.name, prop_type) return prop_type
def find_class_methods(cls): names = set() if not cls.is_abstract(): op = Vips.Operation.new(cls.name) found = False for prop in op.props: flags = op.get_argument_flags(prop.name) if not flags & Vips.ArgumentFlags.INPUT: continue if not flags & Vips.ArgumentFlags.REQUIRED: continue if GObject.type_is_a(vips_type_image, prop.value_type): found = True break if not found: gtype = Vips.type_find("VipsOperation", cls.name) names.add(Vips.nickname_find(gtype)) if len(cls.children) > 0: for child in cls.children: # not easy to get at the deprecated flag in an abtract type? if cls.name != 'VipsWrap7': names.update(find_class_methods(child)) return names
def _check_videosink(): from gi.repository import Gst from gi.repository import Gdk from gi.repository import GObject global videosink_factory try: # If using GdkBroadwayDisplay make sure not to try to use gtkglsink # as it would segfault right away. if GObject.type_is_a(Gdk.Display.get_default().__gtype__, GObject.type_from_name("GdkBroadwayDisplay")): videosink_factory = Gst.ElementFactory.find("gtksink") return True except RuntimeError: pass if "gtkglsink" in os.environ.get("PITIVI_UNSTABLE_FEATURES", ""): sink = Gst.ElementFactory.make("gtkglsink", None) if not sink: videosink_factory = sink.get_factory() elif sink.set_state(Gst.State.READY) == Gst.StateChangeReturn.SUCCESS: videosink_factory = sink.get_factory() sink.set_state(Gst.State.NULL) else: videosink_factory = Gst.ElementFactory.find("gtksink") else: videosink_factory = Gst.ElementFactory.find("gtksink") if videosink_factory: return True return False
def _check_videosink(): from gi.repository import Gst from gi.repository import Gdk from gi.repository import GObject global videosink_factory try: # If using GdkBroadwayDisplay make sure not to try to use gtkglsink # as it would segfault right away. if GObject.type_is_a(Gdk.Display.get_default().__gtype__, GObject.type_from_name("GdkBroadwayDisplay")): videosink_factory = Gst.ElementFactory.find("gtksink") return True except RuntimeError: pass if "gtkglsink" in os.environ.get("PITIVI_UNSTABLE_FEATURES", ''): sink = Gst.ElementFactory.make("gtkglsink", None) if not sink: videosink_factory = sink.get_factory() elif sink.set_state(Gst.State.READY) == Gst.StateChangeReturn.SUCCESS: videosink_factory = sink.get_factory() sink.set_state(Gst.State.NULL) else: videosink_factory = Gst.ElementFactory.find("gtksink") else: videosink_factory = Gst.ElementFactory.find("gtksink") if videosink_factory: return True return False
def arrayize(self, vips_type_array, vips_cast, value): if GObject.type_is_a(self.prop.value_type, vips_type_array): if not isinstance(value, list): value = [value] value = vips_cast(value) return value
def define_class_methods(cls): if not cls.is_abstract(): op = Vips.Operation.new(cls.name) found = False for prop in op.props: flags = op.get_argument_flags(prop.name) if flags & Vips.ArgumentFlags.INPUT and flags & Vips.ArgumentFlags.REQUIRED: if GObject.type_is_a(vips_type_image, prop.value_type): found = True break if not found: gtype = Vips.type_find("VipsOperation", cls.name) nickname = Vips.nickname_find(gtype) logging.debug('adding %s as a class method' % nickname) method = lambda *args, **kwargs: vips_image_class_method( nickname, args, kwargs) setattr(Vips.Image, nickname, classmethod(method)) if len(cls.children) > 0: for child in cls.children: # not easy to get at the deprecated flag in an abtract type? if cls.name != 'VipsWrap7': define_class_methods(child)
def arrayize(gtype, value): for t, cast in arrayize_types: if GObject.type_is_a(gtype, t): if not isinstance(value, list): value = [value] return cast(value) return value
def _using_broadway_display(): from gi.repository import Gdk from gi.repository import GObject try: gdk_broadway_display_type = GObject.type_from_name("GdkBroadwayDisplay") except RuntimeError: return False display = Gdk.Display.get_default() return GObject.type_is_a(display.__gtype__, gdk_broadway_display_type)
def getDBObjectDerived(self, typename, types): children = GObject.type_children(typename) for gtype in children: childname = GObject.type_name(gtype) self.getDBObjectDerived(childname, types) # FIXME, core should support some routines to check if type could have storage if (GObject.type_is_a( gtype, GObject.type_from_name("MidgardBaseInterface")) or gtype.is_abstract() or childname == "MidgardMetadata"): continue types.append(childname)
def getDBObjectDerived(self, typename, types): children = GObject.type_children(typename) for gtype in children: childname = GObject.type_name(gtype) self.getDBObjectDerived(childname, types) # FIXME, core should support some routines to check if type could have storage if (GObject.type_is_a(gtype, GObject.type_from_name("MidgardBaseInterface")) or gtype.is_abstract() or childname == "MidgardMetadata"): continue types.append(childname)
def get_builder_toplevel(self, builder): """Get the toplevel widget from a Gtk.Builder file. The main view implementation first searches for the widget named as self.toplevel_name (which defaults to "main". If this is missing, or not a Gtk.Window, the first toplevel window found in the Gtk.Builder is used. """ toplevel = builder.get_object(self.toplevel_name) if not GObject.type_is_a(toplevel, Gtk.Window): toplevel = None if toplevel is None: toplevel = get_first_builder_window(builder) return toplevel
def vips_set_value(self, field, value): gtype = self.get_typeof(field) logging.debug('assigning %s to %s' % (value, self)) logging.debug('%s needs a %s' % (self, gtype)) # array-ize some types, if necessary value = arrayize(gtype, value) # blob-ize if GObject.type_is_a(gtype, vips_type_blob): if not isinstance(value, Vips.Blob): value = Vips.Blob.new(None, value) self.set(field, value)
def get_types(self, gtype): types = [] for name, module in self.modules.items(): if module is not None: for obj in module.__dict__.values(): try: if GObject.type_is_a(obj.__gtype__, gtype): types.append(obj) types.append(name) except AttributeError: pass return types
def find_first_input_image(op, required): found = False for prop in required: flags = op.get_argument_flags(prop.name) if not flags & Vips.ArgumentFlags.INPUT: continue if GObject.type_is_a(vips_type_image, prop.value_type): found = True break if not found: return None return prop
def set_value(self, field, value): """Set a named item on an Image. Values are converted from Python types to something libvips can swallow. For example, bytes() can be used to set VipsBlob fields. """ gtype = self.get_typeof(field) logger.debug('assigning %s to %s' % (value, self)) logger.debug('%s needs a %s' % (self, gtype)) # blob-ize if GObject.type_is_a(gtype, vips_type_blob): if not isinstance(value, Vips.Blob): value = Vips.Blob.new(None, value) # image-ize if GObject.type_is_a(gtype, vips_type_image): if not isinstance(value, Vips.Image): value = imageize(self, value) # array-ize some types, if necessary value = arrayize(gtype, value) self.set(field, value)
def test_type_is_a(self): self.assertTrue(GObject.type_is_a(CustomBase, GObject.TYPE_OBJECT)) self.assertTrue(GObject.type_is_a(CustomChild, CustomBase)) self.assertTrue(GObject.type_is_a(CustomBase, GObject.GObject)) self.assertTrue(GObject.type_is_a(CustomBase.__gtype__, GObject.TYPE_OBJECT)) self.assertFalse(GObject.type_is_a(GObject.TYPE_OBJECT, CustomBase)) self.assertFalse(GObject.type_is_a(CustomBase, int)) # invalid type self.assertRaises(TypeError, GObject.type_is_a, CustomBase, 1) self.assertRaises(TypeError, GObject.type_is_a, 2, GObject.TYPE_OBJECT) self.assertRaises(TypeError, GObject.type_is_a, 1, 2)
def test_type_is_a(self): self.assertTrue(GObject.type_is_a(CustomBase, GObject.TYPE_OBJECT)) self.assertTrue(GObject.type_is_a(CustomChild, CustomBase)) self.assertTrue(GObject.type_is_a(CustomBase, GObject.GObject)) self.assertTrue( GObject.type_is_a(CustomBase.__gtype__, GObject.TYPE_OBJECT)) self.assertFalse(GObject.type_is_a(GObject.TYPE_OBJECT, CustomBase)) self.assertFalse(GObject.type_is_a(CustomBase, int)) # invalid type self.assertRaises(TypeError, GObject.type_is_a, CustomBase, 1) self.assertRaises(TypeError, GObject.type_is_a, 2, GObject.TYPE_OBJECT) self.assertRaises(TypeError, GObject.type_is_a, 1, 2)
def set_value(self, value): logging.debug('assigning %s to %s' % (value, self.name)) logging.debug('%s needs a %s' % (self.name, self.prop.value_type)) # array-ize some types, if necessary value = self.arrayize(vips_type_array_int, Vips.ArrayInt.new, value) value = self.arrayize(vips_type_array_double, Vips.ArrayDouble.new, value) value = self.arrayize(vips_type_array_image, Vips.ArrayImage.new, value) # blob-ize if GObject.type_is_a(self.prop.value_type, vips_type_blob): if not isinstance(value, Vips.Blob): value = Vips.Blob.new(None, value) logging.debug('assigning %s' % self.prop.value_type) self.op.props.__setattr__(self.name, value)
def set_value(self, value): logging.debug('assigning %s to %s' % (value, self.name)) logging.debug('%s needs a %s' % (self.name, self.prop.value_type)) # array-ize some types, if necessary value = arrayize(self.prop.value_type, value) # blob-ize if GObject.type_is_a(self.prop.value_type, vips_type_blob): if not isinstance(value, Vips.Blob): value = Vips.Blob.new(None, value) # MODIFY input images need to be copied before assigning them if self.flags & Vips.ArgumentFlags.MODIFY: value = value.copy() logging.debug('assigning %s' % self.prop.value_type) self.op.props.__setattr__(self.name, value)
def define_class_methods(cls): if len(cls.children) > 0: for child in cls.children: # not easy to get at the deprecated flag in an abtract type? if cls.name != 'VipsWrap7': define_class_methods(child) elif cls.is_instantiatable(): op = Vips.Operation.new(cls.name) found = False for prop in op.props: flags = op.get_argument_flags(prop.name) if flags & Vips.ArgumentFlags.INPUT and flags & Vips.ArgumentFlags.REQUIRED: if GObject.type_is_a(vips_type_image, prop.value_type): found = True break if not found: gtype = Vips.type_find("VipsOperation", cls.name) nickname = Vips.nickname_find(gtype) logging.debug('adding %s as a class method' % nickname) method = lambda *args, **kwargs: vips_image_class_method( nickname, args, kwargs) setattr(Vips.Image, nickname, classmethod(method))
def find_extension_type(self, gtype, module): module_gtypes = self.__extension_cache[module] try: return module_gtypes[gtype] except KeyError: pass for key in getattr(module, '__all__', module.__dict__): value = getattr(module, key) try: value_gtype = value.__gtype__ except AttributeError: continue if GObject.type_is_a(value_gtype, gtype): module_gtypes[gtype] = value return value module_gtypes[gtype] = None return None
def gen_operation(cls): op = Vips.Operation.new(cls.name) gtype = Vips.type_find("VipsOperation", cls.name) nickname = Vips.nickname_find(gtype) all_required = find_required(op) result = find_first_output(op, all_required) this = find_first_input_image(op, all_required) this_part = '' # shallow copy required = all_required[:] if result != None: required.remove(result) if this != None: required.remove(this) this_part = '(image *Image) ' output = '' for i in range(0, 2): with_options = (i == 1) if with_options: output += '\n\n' go_name = upper_camelcase(nickname) if with_options: go_name += 'Ex' output += '// %s executes the \'%s\' operation\n' % (go_name, nickname) output += '// (see %s at http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/func-list.html)\n' % nickname output += 'func %s%s(%s)' % (this_part, go_name, gen_arg_list(op, required, with_options)) if result != None: output += ' %s' % go_types[result.value_type.name] output += ' {\n' if result != None: output += '\tvar %s %s\n' % (lower_camelcase( result.name), get_type(result)) if with_options: output += '\tif options == nil {\n' output += '\t\toptions = NewOptions()\n' output += '\t}\n' else: output += '\toptions := NewOptions()\n' output += '\tvipsCall("%s", options' % nickname options = [] for prop in all_required: method_name = get_options_method_name(prop) arg_name = '' if prop == this: arg_name = 'image' else: flags = op.get_argument_flags(prop.name) arg_name = lower_camelcase(prop.name) if flags & Vips.ArgumentFlags.OUTPUT: method_name += 'Out' if prop == result: arg_name = '&' + arg_name if GObject.type_is_a(param_enum, prop): arg_name = 'int(%s)' % arg_name options.append('.\n\t\t%s("%s", %s)' % (method_name, prop.name, arg_name)) output += '%s)\n' % ''.join(options) if result != None: output += '\treturn %s\n' % lower_camelcase(result.name) output += '}' return output
args.sort(lambda a, b: a.priority - b.priority) enm = Vips.ArgumentFlags # find all required, unassigned input args required_input = [ x for x in args if x.flags & enm.INPUT and x.flags & enm.REQUIRED and not x.isset ] # do we have a non-None self pointer? this is used to set the first # compatible input arg if self is not None: found = False for x in required_input: if GObject.type_is_a(self, x.prop.value_type): x.set_value(self) required_input.remove(x) found = True break if not found: raise Error('Bad arguments.', 'No %s argument to %s.' % (str(self.__class__), name)) if len(required_input) != len(required): raise Error( 'Wrong number of arguments.', '%s needs %d arguments, you supplied %d' % (name, len(required_input), len(required)))
else: count = str(conv.dest_count) if conv.dest_match == GObject.TYPE_INVALID: s += " dst[%s]=%s" % (count, GObject.type_name(conv.dest_type)) else: s += " dst[%s]=%s - %s" \ % (count, GObject.type_name (conv.dest_match), GObject.type_name (conv.dest_type)) if conv.flags & Ipatch.ConverterFlags.DEST_DERIVED: s += "+ DESCENDANTS" Test.info(s) for i in xrange(0, len(CONVERTER_TYPES)): convTypes = CONVERTER_TYPES[i] if GObject.type_is_a (conv.src_type, GObject.type_name (convTypes[0])) \ and GObject.type_is_a (conv.dest_type, GObject.type_name (convTypes[1])): summaryCounts[i] += 1 break else: summaryOther += 1 Test.info("") Test.msg("Converter type summary:") for i in xrange(0, len(CONVERTER_TYPES)): convTypes = CONVERTER_TYPES[i] Test.msg("%s -> %s: %d" % (convTypes[0], convTypes[1], summaryCounts[i]))
def _errorCreatingAssetCb(self, unused_project, error, id, type): """ The given uri isn't a media file """ if GObject.type_is_a(type, GES.UriClip): error = (id, str(error.domain), error) self._errors.append(error) self._updateProgressbar()
def gen_operation(cls): op = Vips.Operation.new(cls.name) gtype = Vips.type_find("VipsOperation", cls.name) op_name = Vips.nickname_find(gtype) func_name = upper_camelcase(op_name) args = [] decls = [] return_types = [] return_names = [] return_values = [] input_options = [] output_options = [] method_args = [] call_values = [] images_in = 0 images_out = 0 all_props = find_required(op) for prop in all_props: name = lower_camelcase(prop.name) prop_type = get_type(prop) flags = op.get_argument_flags(prop.name) method_name = get_options_method_name(prop) if flags & Vips.ArgumentFlags.OUTPUT: if GObject.type_is_a(vips_type_image, prop.value_type): images_out += 1 else: method_args.append('%s *%s' % (name, prop_type)) return_types.append(prop_type) decls.append('var %s %s' % (name, prop_type)) return_values.append(name) output_options.append('Output%s("%s", &%s),' % (method_name, prop.name, name)) else: if GObject.type_is_a(vips_type_image, prop.value_type): images_in += 1 else: call_values.append(name) method_args.append('%s %s' % (name, prop_type)) args.append('%s %s' % (name, prop_type)) arg_name = name if GObject.type_is_a(param_enum, prop): arg_name = 'int(%s)' % arg_name input_options.append('Input%s("%s", %s),' % (method_name, prop.name, arg_name)) args.append('options ...*Option') decls.append('var err error') return_types.append('error') return_values.append('err') method_args.append('options ...*Option') call_values.append('options...') funcs = [] d = { 'op_name': op_name, 'func_name': func_name, 'args': ', '.join(args), 'decls': '\n\t'.join(decls), 'input_options': '\n\t\t'.join(input_options), 'output_options': '\n\t\t'.join(output_options), 'return_types': ', '.join(return_types), 'return_values': ', '.join(return_values), } funcs.append(emit_func(d)) if images_in == 1 and images_out == 1: d['method_args'] = ', '.join(method_args) d['call_values'] = ', '.join(call_values) funcs.append(emit_method(d)) return '\n'.join(funcs)
def generate_docstring(name): try: op = Vips.Operation.new(name) except TypeError as e: raise Error('No such operator.') if op.get_flags() & Vips.OperationFlags.DEPRECATED: raise Error('No such operator.', 'operator "%s" is deprecated' % name) # find all the args for this op, sort into priority order args = op.get_args() # we are only interested in non-deprecated args args = [y for y in args if not y.flags & Vips.ArgumentFlags.DEPRECATED] enm = Vips.ArgumentFlags # find all required, unassigned input args required_input = [x for x in args if x.flags & enm.INPUT and x.flags & enm.REQUIRED and not x.isset] optional_input = [x for x in args if x.flags & enm.INPUT and not x.flags & enm.REQUIRED and not x.isset] required_output = [x for x in args if x.flags & enm.OUTPUT and x.flags & enm.REQUIRED] optional_output = [x for x in args if x.flags & enm.OUTPUT and not x.flags & enm.REQUIRED] # find the first required input image, if any ... we will be a member # function of this instance member_x = None for i in range(0, len(required_input)): x = required_input[i] if GObject.type_is_a(vips_type_image, x.prop.value_type): member_x = x break description = op.get_description() result = description[0].upper() + description[1:] + ".\n\n" result += "Usage:\n" result += " " + ", ".join([x.name for x in required_output]) + " = " if member_x: result += member_x.name + "." + name + "(" else: result += "Vips.Image." + name + "(" required_input_args = [x.name for x in required_input if x != member_x] result += ", ".join(required_input_args) if len(optional_input) > 0 and len(required_input_args) > 0: result += ", " result += ", ".join([x.name + " = " + x.prop.value_type.name for x in optional_input]) result += ")\n" result += "Where:\n" for x in required_output: result += " " + x.description() + "\n" for x in required_input: result += " " + x.description() + "\n" if len(optional_input) > 0: result += "Keyword parameters:\n" for x in optional_input: result += " " + x.description() + "\n" if len(optional_output) > 0: result += "Extra output options:\n" for x in optional_output: result += " " + x.description() + "\n" return result
def _addWidgets(self, properties, default_btn, use_element_props): """ Prepare a gtk table containing the property widgets of an element. Each property is on a separate row of the table. A row is typically a label followed by the widget and a reset button. If there are no properties, returns a table containing the label "No properties." """ self.bindings = {} self.keyframeToggleButtons = {} is_effect = False if isinstance(self.element, GES.Effect): is_effect = True props = [ prop for prop in self.element.list_children_properties() if prop.name not in self.ignore] else: props = [prop for prop in GObject.list_properties( self.element) if prop.name not in self.ignore] if not props: table = Gtk.Table(n_rows=1, n_columns=1) widget = Gtk.Label(label=_("No properties.")) widget.set_sensitive(False) table.attach(widget, 0, 1, 0, 1, yoptions=Gtk.AttachOptions.FILL) self.pack_start(table, expand=True, fill=True, padding=0) self.show_all() return if default_btn: table = Gtk.Table(n_rows=len(props), n_columns=4) else: table = Gtk.Table(n_rows=len(props), n_columns=3) table.set_row_spacings(SPACING) table.set_col_spacings(SPACING) table.set_border_width(SPACING) y = 0 for prop in props: # We do not know how to work with GObjects, so blacklist # them to avoid noise in the UI if (not prop.flags & GObject.PARAM_WRITABLE or not prop.flags & GObject.PARAM_READABLE or GObject.type_is_a(prop.value_type, GObject.Object)): continue if is_effect: result, prop_value = self.element.get_child_property(prop.name) if result is False: self.debug( "Could not get value for property: %s", prop.name) else: if use_element_props: prop_value = self.element.get_property(prop.name) else: prop_value = properties.get(prop.name) widget = self._makePropertyWidget(prop, prop_value) if isinstance(widget, ToggleWidget): widget.set_label(prop.nick) table.attach( widget, 0, 2, y, y + 1, yoptions=Gtk.AttachOptions.FILL) else: label = Gtk.Label(label=prop.nick + ":") label.set_alignment(0.0, 0.5) table.attach( label, 0, 1, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) table.attach( widget, 1, 2, y, y + 1, yoptions=Gtk.AttachOptions.FILL) if not isinstance(widget, ToggleWidget) and not isinstance(widget, ChoiceWidget) and self.isControllable: button = self._getKeyframeToggleButton(prop) self.keyframeToggleButtons[button] = widget table.attach( button, 3, 4, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) if hasattr(prop, 'blurb'): widget.set_tooltip_text(prop.blurb) self.properties[prop] = widget # The "reset to default" button associated with this property if default_btn: widget.propName = prop.name.split("-")[0] if self.isControllable: # If this element is controlled, the value means nothing # anymore. binding = self.element.get_control_binding(prop.name) if binding: widget.set_sensitive(False) self.bindings[widget] = binding button = self._getResetToDefaultValueButton(prop, widget) table.attach( button, 2, 3, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) self.buttons[button] = widget y += 1 self.element.connect('deep-notify', self._propertyChangedCb) self.pack_start(table, expand=True, fill=True, padding=0) self.show_all()
def gen_operation(cls): op = Vips.Operation.new(cls.name) gtype = Vips.type_find("VipsOperation", cls.name) op_name = Vips.nickname_find(gtype) func_name = upper_camelcase(op_name) args = [] decls = [] return_types = [] return_values = [] input_options = [] output_options = [] method_args = [] call_values = [] images_in = 0 images_out = 0 all_props = find_required(op) for prop in all_props: name = lower_camelcase(prop.name) prop_type = get_type(prop) flags = op.get_argument_flags(prop.name) method_name = get_options_method_name(prop) if flags & Vips.ArgumentFlags.OUTPUT: if GObject.type_is_a(vips_type_image, prop.value_type): images_out += 1 else: method_args.append("%s *%s" % (name, prop_type)) return_types.append(prop_type) decls.append("var %s %s" % (name, prop_type)) return_values.append(name) output_options.append('Output%s("%s", &%s),' % (method_name, prop.name, name)) else: if GObject.type_is_a(vips_type_image, prop.value_type): images_in += 1 else: call_values.append(name) method_args.append("%s %s" % (name, prop_type)) args.append("%s %s" % (name, prop_type)) arg_name = name if GObject.type_is_a(param_enum, prop): arg_name = "int(%s)" % arg_name input_options.append('Input%s("%s", %s),' % (method_name, prop.name, arg_name)) args.append("options ...*Option") decls.append("var err error") return_types.append("error") return_values.append("err") method_args.append("options ...*Option") call_values.append("options...") funcs = [] d = { "op_name": op_name, "func_name": func_name, "args": ", ".join(args), "decls": "\n\t".join(decls), "input_options": "\n\t\t".join(input_options), "output_options": "\n\t\t".join(output_options), "return_types": ", ".join(return_types), "return_values": ", ".join(return_values), } funcs.append(emit_func(d)) if images_in == 1 and images_out == 1: d["method_args"] = ", ".join(method_args) d["call_values"] = ", ".join(call_values) funcs.append(emit_method(d)) return "\n".join(funcs)
def _addWidgets(self, properties, default_btn, use_element_props): """ Prepare a gtk table containing the property widgets of an element. Each property is on a separate row of the table. A row is typically a label followed by the widget and a reset button. If there are no properties, returns a table containing the label "No properties." """ is_effect = False if isinstance(self.element, GES.Effect): is_effect = True props = [prop for prop in self.element.list_children_properties() if not prop.name in self.ignore] else: props = [prop for prop in GObject.list_properties(self.element) if not prop.name in self.ignore] if not props: table = Gtk.Table(rows=1, columns=1) widget = Gtk.Label(label=_("No properties.")) widget.set_sensitive(False) table.attach(widget, 0, 1, 0, 1, yoptions=Gtk.AttachOptions.FILL) self.pack_start(table, True, True, 0) self.show_all() return if default_btn: table = Gtk.Table(rows=len(props), columns=3) else: table = Gtk.Table(rows=len(props), columns=2) table.set_row_spacings(SPACING) table.set_col_spacings(SPACING) table.set_border_width(SPACING) y = 0 for prop in props: # We do not know how to work with GObjects, so blacklist # them to avoid noise in the UI if (not prop.flags & GObject.PARAM_WRITABLE or not prop.flags & GObject.PARAM_READABLE or GObject.type_is_a(prop.value_type, GObject.Object)): continue if is_effect: result, prop_value = self.element.get_child_property(prop.name) if result is False: self.debug("Could not get property %s value", prop.name) else: if use_element_props: prop_value = self.element.get_property(prop.name) else: prop_value = properties.get(prop.name) widget = make_property_widget(self.element, prop, prop_value) if isinstance(widget, ToggleWidget): widget.set_label(prop.nick) table.attach(widget, 0, 2, y, y + 1, yoptions=Gtk.AttachOptions.FILL) else: label = Gtk.Label(label=prop.nick + ":") label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) table.attach(widget, 1, 2, y, y + 1, yoptions=Gtk.AttachOptions.FILL) if hasattr(prop, 'blurb'): widget.set_tooltip_text(prop.blurb) self.properties[prop] = widget # The "reset to default" button associated with this property if default_btn: button = self._getResetToDefaultValueButton(prop, widget) table.attach(button, 2, 3, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) self.buttons[button] = widget self.element.connect('notify::' + prop.name, self._propertyChangedCb, widget) y += 1 self.pack_start(table, True, True, 0) self.show_all()
def generate_docstring(name): try: op = Vips.Operation.new(name) except TypeError as e: raise Error('No such operator.') if op.get_flags() & Vips.OperationFlags.DEPRECATED: raise Error('No such operator.', 'operator "%s" is deprecated' % name) # find all the args for this op, sort into priority order args = op.get_args() # we are only interested in non-deprecated args args = [y for y in args if not y.flags & Vips.ArgumentFlags.DEPRECATED] enm = Vips.ArgumentFlags # find all required, unassigned input args required_input = [ x for x in args if x.flags & enm.INPUT and x.flags & enm.REQUIRED and not x.isset ] optional_input = [ x for x in args if x.flags & enm.INPUT and not x.flags & enm.REQUIRED and not x.isset ] required_output = [ x for x in args if x.flags & enm.OUTPUT and x.flags & enm.REQUIRED ] optional_output = [ x for x in args if x.flags & enm.OUTPUT and not x.flags & enm.REQUIRED ] # find the first required input image, if any ... we will be a member # function of this instance member_x = None for i in range(0, len(required_input)): x = required_input[i] if GObject.type_is_a(vips_type_image, x.prop.value_type): member_x = x break description = op.get_description() result = description[0].upper() + description[1:] + ".\n\n" result += "Usage:\n" result += " " + ", ".join([x.name for x in required_output]) + " = " if member_x: result += member_x.name + "." + name + "(" else: result += "Vips.Image." + name + "(" required_input_args = [x.name for x in required_input if x != member_x] result += ", ".join(required_input_args) if len(optional_input) > 0 and len(required_input_args) > 0: result += ", " result += ", ".join( [x.name + " = " + x.prop.value_type.name for x in optional_input]) result += ")\n" result += "Where:\n" for x in required_output: result += " " + x.description() + "\n" for x in required_input: result += " " + x.description() + "\n" if len(optional_input) > 0: result += "Keyword parameters:\n" for x in optional_input: result += " " + x.description() + "\n" if len(optional_output) > 0: result += "Extra output options:\n" for x in optional_output: result += " " + x.description() + "\n" return result
def _call_base(name, required, optional, self=None, option_string=None): logger.debug('_call_base name=%s, required=%s optional=%s' % (name, required, optional)) if self: logger.debug('_call_base self=%s' % self) if option_string: logger.debug('_call_base option_string = %s' % option_string) try: op = Vips.Operation.new(name) except TypeError as e: raise Error('No such operator.') if op.get_flags() & Vips.OperationFlags.DEPRECATED: raise Error('No such operator.', 'operator "%s" is deprecated' % name) # set str options first so the user can't override things we set # deliberately and break stuff if option_string: if op.set_from_string(option_string) != 0: raise Error('Bad arguments.') args = op.get_args() enm = Vips.ArgumentFlags # find all required, unassigned, undeprecated input args required_input = [ x for x in args if x.flags & enm.INPUT and x.flags & enm.REQUIRED and not x.flags & enm.DEPRECATED and not x.isset ] # do we have a non-None self pointer? this is used to set the first # compatible input arg if self is not None: found = False for x in required_input: if GObject.type_is_a(self, x.prop.value_type): x.set_value(None, self) required_input.remove(x) found = True break if not found: raise Error('Bad arguments.', 'No %s argument to %s.' % (str(self.__class__), name)) if len(required_input) != len(required): raise Error( 'Wrong number of arguments.', '%s needs %d arguments, you supplied %d.' % (name, len(required_input), len(required))) # if we need an image arg but the user supplied a number or list of # numbers, we expand it into an image automatically ... the number is # expanded to match self, or if that's None, the first image we can find in # the required or optional arguments match_image = self if match_image is None: for arg in required: match_image = find_image(arg) if match_image is not None: break if match_image is None: for arg_name in optional: match_image = find_image(optional[arg_name]) if match_image is not None: break for i in range(len(required_input)): required_input[i].set_value(match_image, required[i]) # find all optional, unassigned input args ... make a hash from name to # Argument # we let deprecated ones through, we want to allow assigment to them for # compat optional_input = { x.name: x for x in args if x.flags & enm.INPUT and not x.flags & enm.REQUIRED and not x.isset } # find all optional output args ... we use "x = True" # in args to mean add that to output optional_output = { x.name: x for x in args if x.flags & enm.OUTPUT and not x.flags & enm.REQUIRED } # set optional input args for key in list(optional.keys()): if key in optional_input: optional_input[key].set_value(match_image, optional[key]) elif key in optional_output: # must be a literal True value if optional[key] is not True: raise Error('Optional output argument must be True.', 'Argument %s should equal True.' % key) else: raise Error('Unknown argument.', 'Operator %s has no argument %s.' % (name, key)) # call logger.debug('_call_base checking cache for op %s' % op) op2 = Vips.cache_operation_build(op) logger.debug('_call_base got op2 %s' % op2) if op2 == None: raise Error('Error calling operator %s.' % name) # rescan args if op2 is different from op if op2 != op: logger.debug('_call_base rescanning args') args = op2.get_args() optional_output = { x.name: x for x in args if x.flags & enm.OUTPUT and not x.flags & enm.REQUIRED } # gather output args logger.debug('_call_base fetching required output args') out = [] for x in args: # required non-deprecated output arg if x.flags & enm.OUTPUT and x.flags & enm.REQUIRED and not x.flags & enm.DEPRECATED: out.append(x.get_value()) # modified input arg ... this will get the memory image we made above if x.flags & enm.INPUT and x.flags & enm.MODIFY: out.append(x.get_value()) logger.debug('_call_base fetching optional output args') out_dict = {} for x in list(optional.keys()): if x in optional_output: out_dict[x] = optional_output[x].get_value() if out_dict != {}: out.append(out_dict) if len(out) == 1: out = out[0] elif len(out) == 0: out = None # unref everything now we have refs to all outputs we want op2.unref_outputs() logger.debug('success') return out
def __add_widgets(self, values, with_reset_button): """Prepares a Gtk.Grid containing the property widgets of an element. Each property is on a separate row. A row is typically a label followed by the widget and a reset button. If there are no properties, returns a "No properties" label. """ self.properties.clear() self.__bindings_by_keyframe_button = {} self.__widgets_by_keyframe_button = {} is_effect = isinstance(self.element, GES.Effect) if is_effect: props = [ prop for prop in self.element.list_children_properties() if prop.name not in self.ignore ] else: props = [ prop for prop in GObject.list_properties(self.element) if prop.name not in self.ignore ] if not props: widget = Gtk.Label(label=_("No properties.")) self.pack_start(widget, expand=False, fill=False, padding=0) widget.show() return grid = Gtk.Grid() grid.props.row_spacing = SPACING grid.props.column_spacing = SPACING grid.props.border_width = SPACING for y, prop in enumerate(props): # We do not know how to work with GObjects, so blacklist # them to avoid noise in the UI if (not prop.flags & GObject.PARAM_WRITABLE or not prop.flags & GObject.PARAM_READABLE or GObject.type_is_a(prop.value_type, GObject.Object)): continue if is_effect: result, prop_value = self.element.get_child_property(prop.name) if not result: self.debug("Could not get value for property: %s", prop.name) else: if prop.name not in values.keys(): # Use the default value. prop_value = self.element.get_property(prop.name) else: prop_value = values[prop.name] widget = self._makePropertyWidget(prop, prop_value) if isinstance(widget, ToggleWidget): widget.set_label(prop.nick) grid.attach(widget, 0, y, 2, 1) else: text = _("%(preference_label)s:") % { "preference_label": prop.nick } label = Gtk.Label(label=text) label.set_alignment(0.0, 0.5) grid.attach(label, 0, y, 1, 1) grid.attach(widget, 1, y, 1, 1) if hasattr(prop, 'blurb'): widget.set_tooltip_text(prop.blurb) self.properties[prop] = widget if not self.__controllable or isinstance(widget, DefaultWidget): continue keyframe_button = None if not isinstance(widget, (ToggleWidget, ChoiceWidget)): res, element, pspec = self.element.lookup_child(prop.name) assert res binding = GstController.DirectControlBinding.new( element, prop.name, GstController.InterpolationControlSource()) if binding.pspec: # The prop can be controlled (keyframed). keyframe_button = self.__create_keyframe_toggle_button( prop, widget) grid.attach(keyframe_button, 2, y, 1, 1) # The "reset to default" button associated with this property if with_reset_button: button = self.__create_reset_to_default_button( prop, widget, keyframe_button) grid.attach(button, 3, y, 1, 1) self.element.connect('deep-notify', self._propertyChangedCb) self.pack_start(grid, expand=False, fill=False, padding=0) self.show_all()
def get_options_method_name(prop): # Enums use their values if GObject.type_is_a(param_enum, prop): return "Int" return options_method_names[prop.value_type.name]
def assertElementAreEqual(self, ref, element): self.assertTrue( isinstance(element, type(ref)), "%s and %s do not have the same type!" % (ref, element)) props = [ p for p in ref.list_properties() if p.name not in ['name'] and not GObject.type_is_a(p.value_type, GObject.Object) ] for p in props: pname = p.name refval = GObject.Value() refval.init(p.value_type) refval.set_value(ref.get_property(pname)) value = GObject.Value() value.init(p.value_type) value.set_value(element.get_property(pname)) self.assertTrue( Gst.value_compare(refval, value) == Gst.VALUE_EQUAL, "%s are not equal: %s != %s\n %s != %s" % (pname, value, refval, element, ref)) if isinstance(ref, GES.TrackElement): self.assertElementAreEqual(ref.get_nleobject(), element.get_nleobject()) return if not isinstance(ref, GES.Clip): return ttypes = [track.type for track in self.timeline.get_tracks()] for ttype in ttypes: if ttypes.count(ttype) > 1: self.warning( "Can't deeply check %s and %s " "(only one track per type supported %s %s found)" % (ref, element, ttypes.count(ttype), ttype)) return children = element.get_children(False) for ref_child in ref.get_children(False): ref_track = ref_child.get_track() if not ref_track: self.warning("Can't check %s as not in a track" % (ref_child)) continue child = None for tmpchild in children: if not isinstance(tmpchild, type(ref_child)): continue if ref_track.type != tmpchild.get_track().type: continue if not isinstance(ref_child, GES.Effect): child = tmpchild break elif ref_child.props.bin_description == tmpchild.props.bin_description: child = tmpchild break self.assertIsNotNone( child, "Could not find equivalent child %s in %s(%s)" % (ref_child, element, children)) self.assertElementAreEqual(ref_child, child)
def _call_base(name, required, optional, self = None, option_string = None): logger.debug('_call_base name=%s, required=%s optional=%s' % (name, required, optional)) if self: logger.debug('_call_base self=%s' % self) if option_string: logger.debug('_call_base option_string = %s' % option_string) try: op = Vips.Operation.new(name) except TypeError as e: raise Error('No such operator.') if op.get_flags() & Vips.OperationFlags.DEPRECATED: raise Error('No such operator.', 'operator "%s" is deprecated' % name) # set str options first so the user can't override things we set # deliberately and break stuff if option_string: if op.set_from_string(option_string) != 0: raise Error('Bad arguments.') args = op.get_args() enm = Vips.ArgumentFlags # find all required, unassigned, undeprecated input args required_input = [x for x in args if x.flags & enm.INPUT and x.flags & enm.REQUIRED and not x.flags & enm.DEPRECATED and not x.isset] # do we have a non-None self pointer? this is used to set the first # compatible input arg if self is not None: found = False for x in required_input: if GObject.type_is_a(self, x.prop.value_type): x.set_value(None, self) required_input.remove(x) found = True break if not found: raise Error('Bad arguments.', 'No %s argument to %s.' % (str(self.__class__), name)) if len(required_input) != len(required): raise Error('Wrong number of arguments.', '%s needs %d arguments, you supplied %d.' % (name, len(required_input), len(required))) # if we need an image arg but the user supplied a number or list of # numbers, we expand it into an image automatically ... the number is # expanded to match self, or if that's None, the first image we can find in # the required or optional arguments match_image = self if match_image is None: for arg in required: match_image = find_image(arg) if match_image is not None: break if match_image is None: for arg_name in optional: match_image = find_image(optional[arg_name]) if match_image is not None: break for i in range(len(required_input)): required_input[i].set_value(match_image, required[i]) # find all optional, unassigned input args ... make a hash from name to # Argument # we let deprecated ones through, we want to allow assigment to them for # compat optional_input = {x.name: x for x in args if x.flags & enm.INPUT and not x.flags & enm.REQUIRED and not x.isset} # find all optional output args ... we use "x = True" # in args to mean add that to output optional_output = {x.name: x for x in args if x.flags & enm.OUTPUT and not x.flags & enm.REQUIRED} # set optional input args for key in list(optional.keys()): if key in optional_input: optional_input[key].set_value(match_image, optional[key]) elif key in optional_output: # must be a literal True value if optional[key] is not True: raise Error('Optional output argument must be True.', 'Argument %s should equal True.' % key) else: raise Error('Unknown argument.', 'Operator %s has no argument %s.' % (name, key)) # call logger.debug('_call_base checking cache for op %s' % op) op2 = Vips.cache_operation_build(op) logger.debug('_call_base got op2 %s' % op2) if op2 == None: raise Error('Error calling operator %s.' % name) # rescan args if op2 is different from op if op2 != op: logger.debug('_call_base rescanning args') args = op2.get_args() optional_output = {x.name: x for x in args if x.flags & enm.OUTPUT and not x.flags & enm.REQUIRED} # gather output args logger.debug('_call_base fetching required output args') out = [] for x in args: # required non-deprecated output arg if x.flags & enm.OUTPUT and x.flags & enm.REQUIRED and not x.flags & enm.DEPRECATED: out.append(x.get_value()) # modified input arg ... this will get the memory image we made above if x.flags & enm.INPUT and x.flags & enm.MODIFY: out.append(x.get_value()) logger.debug('_call_base fetching optional output args') out_dict = {} for x in list(optional.keys()): if x in optional_output: out_dict[x] = optional_output[x].get_value() if out_dict != {}: out.append(out_dict) if len(out) == 1: out = out[0] elif len(out) == 0: out = None # unref everything now we have refs to all outputs we want op2.unref_outputs() logger.debug('success') return out
def get_ctype(prop): # enum params use the C name as their name if GObject.type_is_a(param_enum, prop): return prop.value_type.name return gtype_to_cpp[prop.value_type.name]
args = [Argument(op, x) for x in op.props] args.sort(lambda a, b: a.priority - b.priority) enm = Vips.ArgumentFlags # find all required, unassigned input args required_input = [x for x in args if x.flags & enm.INPUT and x.flags & enm.REQUIRED and not x.isset] # do we have a non-NULL self pointer? this is used to set the first # compatible input arg if self != None: found = False for x in required_input: if GObject.type_is_a(self, x.prop.value_type): op.props.__setattr__(x.name, self) required_input.remove(x) found = True break if not found: raise Error('Bad arguments.', 'No %s argument to %s.' % (str(self.__class__), name)) if len(required_input) != len(required): raise Error('Wrong number of arguments.', '"%s" needs %d arguments, you supplied %d' % (name, len(required_input), len(required))) for i in range(len(required_input)):
def _get_pspec_args(self): if GObject.type_is_a(self.type, GObject.GEnum): return (self.type, self.nick, self.blurb, self.default, self.flags) else: return parent_get_pspec_args(self)
def _addWidgets(self, properties, default_btn, use_element_props): """ Prepare a gtk table containing the property widgets of an element. Each property is on a separate row of the table. A row is typically a label followed by the widget and a reset button. If there are no properties, returns a table containing the label "No properties." """ is_effect = False if isinstance(self.element, GES.Effect): is_effect = True props = [ prop for prop in self.element.list_children_properties() if not prop.name in self.ignore ] else: props = [ prop for prop in GObject.list_properties(self.element) if not prop.name in self.ignore ] if not props: table = Gtk.Table(rows=1, columns=1) widget = Gtk.Label(label=_("No properties.")) widget.set_sensitive(False) table.attach(widget, 0, 1, 0, 1, yoptions=Gtk.AttachOptions.FILL) self.pack_start(table, True, True, 0) self.show_all() return if default_btn: table = Gtk.Table(rows=len(props), columns=3) else: table = Gtk.Table(rows=len(props), columns=2) table.set_row_spacings(SPACING) table.set_col_spacings(SPACING) table.set_border_width(SPACING) y = 0 for prop in props: # We do not know how to work with GObjects, so blacklist # them to avoid noise in the UI if (not prop.flags & GObject.PARAM_WRITABLE or not prop.flags & GObject.PARAM_READABLE or GObject.type_is_a(prop.value_type, GObject.Object)): continue if is_effect: result, prop_value = self.element.get_child_property(prop.name) if result is False: self.debug("Could not get property %s value", prop.name) else: if use_element_props: prop_value = self.element.get_property(prop.name) else: prop_value = properties.get(prop.name) widget = make_property_widget(self.element, prop, prop_value) if isinstance(widget, ToggleWidget): widget.set_label(prop.nick) table.attach(widget, 0, 2, y, y + 1, yoptions=Gtk.AttachOptions.FILL) else: label = Gtk.Label(label=prop.nick + ":") label.set_alignment(0.0, 0.5) table.attach(label, 0, 1, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) table.attach(widget, 1, 2, y, y + 1, yoptions=Gtk.AttachOptions.FILL) if hasattr(prop, 'blurb'): widget.set_tooltip_text(prop.blurb) self.properties[prop] = widget # The "reset to default" button associated with this property if default_btn: button = self._getResetToDefaultValueButton(prop, widget) table.attach(button, 2, 3, y, y + 1, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL) self.buttons[button] = widget self.element.connect('notify::' + prop.name, self._propertyChangedCb, widget) y += 1 self.pack_start(table, True, True, 0) self.show_all()
def __add_widgets(self, values, with_reset_button): """ Prepare a Gtk.Grid containing the property widgets of an element. Each property is on a separate row. A row is typically a label followed by the widget and a reset button. If there are no properties, returns a "No properties" label. """ self.properties.clear() self.__bindings_by_keyframe_button = {} self.__widgets_by_keyframe_button = {} is_effect = isinstance(self.element, GES.Effect) if is_effect: props = [prop for prop in self.element.list_children_properties() if prop.name not in self.ignore] else: props = [prop for prop in GObject.list_properties(self.element) if prop.name not in self.ignore] if not props: widget = Gtk.Label(label=_("No properties.")) self.pack_start(widget, expand=False, fill=False, padding=0) widget.show() return grid = Gtk.Grid() grid.props.row_spacing = SPACING grid.props.column_spacing = SPACING grid.props.border_width = SPACING for y, prop in enumerate(props): # We do not know how to work with GObjects, so blacklist # them to avoid noise in the UI if (not prop.flags & GObject.PARAM_WRITABLE or not prop.flags & GObject.PARAM_READABLE or GObject.type_is_a(prop.value_type, GObject.Object)): continue if is_effect: result, prop_value = self.element.get_child_property(prop.name) if not result: self.debug( "Could not get value for property: %s", prop.name) else: if not values: # Use the default value. prop_value = self.element.get_property(prop.name) else: prop_value = values.get(prop.name) widget = self._makePropertyWidget(prop, prop_value) if isinstance(widget, ToggleWidget): widget.set_label(prop.nick) grid.attach(widget, 0, y, 2, 1) else: text = _("%(preference_label)s:") % {"preference_label": prop.nick} label = Gtk.Label(label=text) label.set_alignment(0.0, 0.5) grid.attach(label, 0, y, 1, 1) grid.attach(widget, 1, y, 1, 1) if hasattr(prop, 'blurb'): widget.set_tooltip_text(prop.blurb) self.properties[prop] = widget if not self.__controllable or isinstance(widget, DefaultWidget): continue keyframe_button = None if not isinstance(widget, (ToggleWidget, ChoiceWidget)): res, element, pspec = self.element.lookup_child(prop.name) assert(res) binding = GstController.DirectControlBinding.new( element, prop.name, GstController.InterpolationControlSource()) if binding.pspec: # The prop can be controlled (keyframed). keyframe_button = self.__create_keyframe_toggle_button(prop, widget) grid.attach(keyframe_button, 2, y, 1, 1) # The "reset to default" button associated with this property if with_reset_button: button = self.__create_reset_to_default_button(prop, widget, keyframe_button) grid.attach(button, 3, y, 1, 1) self.element.connect('deep-notify', self._propertyChangedCb) self.pack_start(grid, expand=False, fill=False, padding=0) self.show_all()