def to_string_array(cls, actual_arg): """ Return GValue holding instance of type GStrv created from actual_arg """ # Fail: GStrv is not a GType, only a C typedef. # Fail: GObject.TYPE_BOXED, cannot initialize GValue with type 'GBoxed', this type has no GTypeValueTable implementation # Fail: GLib.VariantType # G_TYPE_STRV # Setter is not a GIMP method, but a method of GObject.Value # See GObject>Structures>Value # Fail: self.to_gimp_array(GObject.TYPE_STRV, GObject.Value.set_boxed ) # Fail: gvalue = FuGenericValueArray.to_gimp_array(actual_arg, GObject.TYPE_STRV, GObject.Value.set_variant ) cls.logger.info(f"to_string_array") # require a sequence try: a_list = FuGenericValueArray.sequence_for_actual_arg(actual_arg) except Exception as err: proceed( f"Exception in sequence_for_actual_arg: _actual_arg: {actual_arg}, {err}" ) # Create GObject.Value ''' gvalue = GObject.Value(GObject.TYPE_STRV, a_list) ''' ''' try: # create empty (i.e. no value) GValue of desired type, gvalue = GObject.Value (GObject.TYPE_STRV) except Exception as err: proceed(f"Fail to create GObject.Value for array, err is: {err}.") # GObject.GStrv is not a class? # Code lifted from PyGObject/tests/test_properties.property # GStrv inherits Python list type class GStrv(list): __gtype__ = GObject.TYPE_STRV # Create instance from instance of Python list type gstrv = GStrv(a_list) # put instance in the gvalue. gvalue.set_boxed(gstrv) ''' gvalue = GObject.Value(GObject.TYPE_STRV) gvalue.set_boxed(a_list) assert GObject.type_check_value_holds(gvalue, GObject.TYPE_STRV) return gvalue
def _eventLoop(self, block=True, doProgress=False, targetState=Gst.State.PLAYING): ''' This is the main loop that processes information on the bus and decides how the pipeline should react. Sometimes this entails spitting out messages, others it involves changing state or some other manipulation. ''' buffering = False inProgress = False prerolled = targetState != Gst.State.PAUSED pName = self._pipeline.get_name() bus = self._pipeline.get_bus() while not self._stopper.isSet(): # TODO: if we actually want to stop the pipeline asyncronously we # need to post a message on the bus that tells it to stop. Otherwise # it will wait here forever (or will be terminated as a daemon # thread by its parent) msg = bus.timed_pop(1e18 if block else 0) if not msg: return msgSrc = msg.src msgSrcName = msgSrc.get_name() msgType = msg.type msgTypeName = Gst.MessageType.get_name(msgType) # messages that involve manipulating the pipeline if msgType == Gst.MessageType.REQUEST_STATE: state = msg.parse_request_state() logger.info('Setting state to %s as requested by %s', state.value_name, msgSrcName) self._pipeline.set_state(state) elif msgType == Gst.MessageType.CLOCK_LOST: logger.debug('Clock lost. Getting new one.') self._pipeline.set_state(Gst.State.PAUSED) self._pipeline.set_state(Gst.State.PLAYING) elif msgType == Gst.MessageType.LATENCY: _gstPrintMsg(pName, 'Redistributing latency', sName=msgSrcName) self._pipeline.recalculate_latency() # messages that do not require pipeline manipulation elif msgType == Gst.MessageType.BUFFERING: _gstPrintMsg(pName, 'Buffering: {}', msg.parse_buffering(), sName=msgSrcName) elif msgType == Gst.MessageType.NEW_CLOCK: clock = msg.parse_new_clock() clock = clock.get_name() if clock else 'NULL' _gstPrintMsg(pName, 'New clock: {}', clock) elif msgType == Gst.MessageType.INFO: error, debug = msg.parse_info() if debug: _gstPrintMsg(pName, debug, level=logging.INFO, sName=msgSrcName) elif msgType == Gst.MessageType.WARNING: error, debug = msg.parse_warning() if debug: _gstPrintMsg(pName, '{} - Additional debug info: {}', error.message, debug, level=logging.WARNING, sName=msgSrcName) else: _gstPrintMsg(pName, error.message, level=logging.WARNING, sName=msgSrcName) elif msgType == Gst.MessageType.ERROR: _processErrorMessage(pName, msgSrcName, msg) elif msgType == Gst.MessageType.STATE_CHANGED: # we only care about pipeline level state changes if msgSrc == self._pipeline: old, new, pending = msg.parse_state_changed() # we only care if we reach the final target state if targetState == Gst.State.PAUSED and new == Gst.State.PAUSED: prerolled = True if buffering: _gstPrintMsg( pName, 'Prerolled, waiting for buffering to finish', level=logging.INFO) continue if inProgress: _gstPrintMsg( pName, 'Prerolled, waiting for progress to finish', level=logging.INFO) continue return elif msgType == Gst.MessageType.PROGRESS: progressType, code, text = msg.parse_progress() if (progressType == Gst.ProgressType.START or progressType == Gst.ProgressType.CONTINUE): if doProgress: inProgress = True block = True elif (progressType == Gst.ProgressType.COMPLETE or progressType == Gst.ProgressType.CANCELLED or progressType == Gst.ProgressType.ERROR): inProgress = False _gstPrintMsg(pName, 'Progress: ({}) {}', code, text, sName=msgSrcName) if doProgress and not inProgress and not buffering and prerolled: return elif msgType == Gst.MessageType.HAVE_CONTEXT: context = msg.parse_have_context() _gstPrintMsg(pName, 'Got context: {}={}', context.get_context_type(), context.get_structure().to_string(), sName=msgSrcName) elif msgType == Gst.MessageType.PROPERTY_NOTIFY: obj, propName, val = msg.parse_property_notify() valStr = '(no value)' if val: if GObject.type_check_value_holds(val, GObject.TYPE_STRING): valStr = val.dup_string() elif val.g_type.is_a(Gst.Caps.__gtype__): valStr = val.get_boxed().to_string() else: valStr = Gst.value_serialize(val) _gstPrintMsg(pName, '{}: {} = {}', obj.get_name(), propName, valStr, sName=msgSrcName) # these are things I might not need... elif msgType == Gst.MessageType.STREAM_START: if msgSrc == self._pipeline: _gstPrintMsg(pName, 'Started stream', level=logging.INFO) elif msgType == Gst.MessageType.QOS: frmt, processed, dropped = msg.parse_qos_stats() jitter, proportion, quality = msg.parse_qos_values() _gstPrintMsg(pName, 'QOS stats: jitter={} dropped={}', jitter, '-' if frmt == Gst.Format.UNDEFINED else dropped, sName=msgSrcName) elif msgType == Gst.MessageType.ELEMENT: _gstPrintMsg(pName, 'Unknown message ELEMENT', sName=msgSrcName) elif msgType == Gst.MessageType.UNKNOWN: _gstPrintMsg(pName, 'Unknown message', sName=msgSrcName)