예제 #1
0
    def __set_control_bindings(self):
        adding_kfs = not self.__source_uses_keyframes()

        if adding_kfs:
            self.app.action_log.begin(
                "Transformation properties keyframes activate", toplevel=True)

        for prop in ["posx", "posy", "width", "height"]:
            binding = self.source.get_control_binding(prop)

            if not binding:
                control_source = GstController.InterpolationControlSource()
                control_source.props.mode = GstController.InterpolationMode.LINEAR
                self.__own_bindings_change = True
                self.source.set_control_source(control_source, prop,
                                               "direct-absolute")
                self.__own_bindings_change = False
                self.__set_default_keyframes_values(control_source, prop)

                binding = self.source.get_control_binding(prop)
            self.__control_bindings[prop] = binding

        if adding_kfs:
            self.app.action_log.commit(
                "Transformation properties keyframes activate")
예제 #2
0
 def _get_control_source(self, elem, prop='alpha'):
     ctrl = elem.get_control_binding(prop)
     if ctrl:
         return ctrl.get_property('control_source')
     cs = GstController.InterpolationControlSource()
     cs.set_property('mode', GstController.InterpolationMode.LINEAR)
     cb = GstController.DirectControlBinding.new(elem, prop, cs)
     elem.add_control_binding(cb)
     return cs
예제 #3
0
    def __createControlBinding(self, element):
        if self.__controlledProperty:
            element.connect("control-binding-added",
                            self.__controlBindingAddedCb)
            binding = \
                element.get_control_binding(self.__controlledProperty.name)

            if binding:
                self.__createKeyframeCurve(binding)

                return

            source = GstController.InterpolationControlSource()
            source.props.mode = GstController.InterpolationMode.LINEAR
            element.set_control_source(source, self.__controlledProperty.name,
                                       "direct")
예제 #4
0
    def __createControlBinding(self, element):
        """Creates the required ControlBinding and keyframes."""
        if self.__controlledProperty:
            element.connect("control-binding-added",
                            self.__controlBindingAddedCb)
            binding = \
                element.get_control_binding(self.__controlledProperty.name)

            if binding:
                self.__ensure_keyframes(binding)

                return

            source = GstController.InterpolationControlSource()
            source.props.mode = GstController.InterpolationMode.LINEAR
            element.set_control_source(source, self.__controlledProperty.name,
                                       "direct")
예제 #5
0
    def testControlSourceValueChanged(self):
        uri = common.get_sample_uri("tears_of_steel.webm")
        asset = GES.UriClipAsset.request_sync(uri)
        clip = asset.extract()
        self.layer.add_clip(clip)
        source = clip.get_children(False)[1]
        self.assertTrue(isinstance(source, GES.VideoUriSource))

        control_source = GstController.InterpolationControlSource()
        control_source.props.mode = GstController.InterpolationMode.LINEAR
        source.set_control_source(control_source, "alpha", "direct")
        self.assertTrue(control_source.set(Gst.SECOND * 0.5, 0.2))

        with self.action_log.started("keyframe changed"):
            self.assertTrue(control_source.set(Gst.SECOND * 0.5, 0.9))

        self.assertEqual(0.9, control_source.get_all()[0].value)
        self.action_log.undo()
        self.assertEqual(0.2, control_source.get_all()[0].value)
        self.action_log.redo()
        self.assertEqual(0.9, control_source.get_all()[0].value)
예제 #6
0
    def showKeyframes(self, element, propname, isDefault=False):
        binding = element.get_control_binding(propname.name)
        if not binding:
            source = GstController.InterpolationControlSource()
            source.props.mode = GstController.InterpolationMode.LINEAR
            if not (element.set_control_source(source, propname.name, "direct")):
                print("There was something like a problem captain")
                return
            binding = element.get_control_binding(propname.name)

        self.binding = binding
        self.prop = propname
        self.keyframedElement = element
        self.source = self.binding.props.control_source

        if isDefault:
            self.default_prop = propname
            self.default_element = element

        self.keyframesVisible = True

        self.updateKeyframes()
예제 #7
0
        def __init__(self):

            print("Init GStreamer...")

            # This is used to keep track of time between callbacks.
            self.player_timer = Timer()

            # Store the track object that is currently playing
            self.loaded_track = None

            # This is used to keep note of what state of playing we should be in
            self.play_state = 0  # 0 is stopped, 1 is playing, 2 is paused

            # Initiate GSteamer
            Gst.init([])
            self.mainloop = GLib.MainLoop()

            # Populate list of output devices with defaults
            outputs = {}
            devices = [
                "PulseAudio",
                "ALSA",
                "JACK",
            ]
            if tauon.snap_mode:  # Snap permissions don't support these by default
                devices.remove("JACK")
                devices.remove("ALSA")

            # Get list of available audio device
            self.dm = Gst.DeviceMonitor()
            self.dm.start()
            for device in self.dm.get_devices():
                if device.get_device_class() == "Audio/Sink":
                    element = device.create_element(None)
                    type_name = element.get_factory().get_name()
                    if hasattr(element.props, "device"):
                        device_name = element.props.device
                        display_name = device.get_display_name()

                        # This is used by the UI to present list of options to the user in audio settings
                        outputs[display_name] = (type_name, device_name)
                        devices.append(display_name)

            # dm.stop()  # Causes a segfault sometimes
            pctl.gst_outputs = outputs
            pctl.gst_devices = devices

            # Create main "playbin" pipeline for playback
            self.playbin = Gst.ElementFactory.make("playbin", "player")

            # Create custom output bin from user preferences
            if not prefs.gst_use_custom_output:
                prefs.gst_output = prefs.gen_gst_out()

            self._output = Gst.parse_bin_from_description(
                prefs.gst_output, ghost_unlinked_pads=True)

            # Create a bin for the audio pipeline
            self._sink = Gst.ElementFactory.make("bin", "sink")
            self._sink.add(self._output)

            # Spectrum -------------------------
            # Cant seem to figure out how to process these magnitudes in a way that looks good

            # self.spectrum = Gst.ElementFactory.make("spectrum", "spectrum")
            # self.spectrum.set_property('bands', 20)
            # self.spectrum.set_property('interval', 10000000)
            # self.spectrum.set_property('threshold', -100)
            # self.spectrum.set_property('post-messages', True)
            # self.spectrum.set_property('message-magnitude', True)
            #
            # self.playbin.set_property('audio-filter', self.spectrum)
            # # ------------------------------------

            # # Level Meter -------------------------
            self.level = Gst.ElementFactory.make("level", "level")
            self.level.set_property('interval', 20000000)
            self.playbin.set_property('audio-filter', self.level)
            # # ------------------------------------

            self._eq = Gst.ElementFactory.make("equalizer-nbands", "eq")
            self._vol = Gst.ElementFactory.make("volume", "volume")

            self._sink.add(self._eq)
            self._sink.add(self._vol)

            self._eq.link(self._vol)
            self._vol.link(self._output)

            self._eq.set_property("num-bands", 10 + 2)

            # Set the equalizer based on user preferences

            # Using workaround for "inverted slider" bug.
            # Thanks to Lollypop and Clementine for discovering this.
            # Ref https://github.com/Taiko2k/TauonMusicBox/issues/414

            for i in range(10 + 2):
                band = self._eq.get_child_by_index(i)
                band.set_property("freq", 0)
                band.set_property("bandwidth", 0)
                band.set_property("gain", 0)

            self.set_eq()
            # if prefs.use_eq:
            #     self._eq.set_property("band" + str(i), level * -1)
            # else:
            #     self._eq.set_property("band" + str(i), 0.0)

            # Set up sink pad for the intermediate bin via the
            # first element (volume)
            ghost = Gst.GhostPad.new("sink", self._eq.get_static_pad("sink"))
            self._sink.add_pad(ghost)

            # Connect the playback bin to to the intermediate bin sink pad
            self.playbin.set_property("audio-sink", self._sink)

            # The pipeline should look something like this -
            # (player) -> [(eq) -> (volume) -> (output)]

            # Create controller for pause/resume volume fading
            self.c_source = GstController.InterpolationControlSource()
            self.c_source.set_property('mode',
                                       GstController.InterpolationMode.LINEAR)
            self.c_binding = GstController.DirectControlBinding.new(
                self._vol, "volume", self.c_source)
            self._vol.add_control_binding(self.c_binding)

            # Set callback for the main callback loop
            GLib.timeout_add(50, self.main_callback)

            self.playbin.connect("about-to-finish",
                                 self.about_to_finish)  # Not used

            # Setup bus and select what types of messages we want to listen for
            bus = self.playbin.get_bus()
            bus.add_signal_watch()
            bus.connect('message::element', self.on_message)
            bus.connect('message::buffering', self.on_message)
            bus.connect('message::error', self.on_message)
            bus.connect('message::tag', self.on_message)
            bus.connect('message::warning', self.on_message)
            # bus.connect('message::eos', self.on_message)

            # Variables used with network downloading
            self.temp_id = "a"
            self.url = None
            self.dl_ready = True
            self.using_cache = False
            self.temp_path = ""  # Full path + filename
            # self.level_train = []
            self.seek_timer = Timer()
            self.seek_timer.force_set(10)
            self.buffering = False
            # Other
            self.end_timer = Timer()

            # Start GLib mainloop
            self.mainloop.run()
예제 #8
0
    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()
예제 #9
0
    def __init__(self, filename="default.gst", config=dict()):
        self.eventhandlers = dict()
        self.eventkeys = dict()
        self.restart = False
        self.controller = dict()
        self.setter = dict()
        self.pipestring = ""

        self.pipeline = None
        self.bus = None
        self.previewOut = None
        self.liveOut = None
        self.recorder = None

        self.config = config

        conffile = None
        log.info("pipefile: %s" % (filename))

        extension = ".gst"
        if filename.endswith(extension):
            conffile = filename[:-len(extension)] + ".ctl"

        # (self.pipestring, ctrls) =
        #     _pipeParseCtrl(_pipeRead(filename, config))
        self.pipestring = _pipeRead(filename, config)
        ctrls = _ctrlRead(conffile)

        log.info("pipeline: %s" % (self.pipestring))
        log.info("ctrls: %s" % (ctrls))

        self.setEventHandlers({Gst.MessageType.EOS: self._EOS})
        self.setEventHandlers(
            {Gst.MessageType.ELEMENT: self._handleElementEvent})

        self.setEventKeys(None)

        self.pipeline = Gst.parse_launch(self.pipestring)
        self.bus = self.pipeline.get_bus()
        self.bus.add_watch(GLib.PRIORITY_DEFAULT, self._async_handler, None)
        # # enabling the following triggers an assertion (and exists)
        # Gst.Bus.add_signal_watch(self.bus)

        self.previewOut = self.pipeline.get_by_name("preview")
        self.liveOut = self.pipeline.get_by_name("preview")
        self.recorder = self.pipeline.get_by_name("recorder")

        log.info("OUT: %s\t%s", self.previewOut, self.liveOut)

        # get all controllables
        control_dict = {}
        try:
            pipelements = iter(self.pipeline.iterate_elements())
        except TypeError:
            log.exception("'python3-gst-1.0' required?")
            return
        for lmn in pipelements:
            for p in lmn.props:
                if False and p.flags & Gst.PARAM_CONTROLLABLE:
                    if lmn.props.name not in control_dict:
                        control_dict[lmn.props.name] = []
                    control_dict[lmn.props.name] += [p.name]

        if ctrls:
            for ctl, elemprop in ctrls.items():
                # ctl = 'FOO'
                # elemprop = {
                #     'textoverlay_3': ['xpos'],
                #     'textoverlay_1': ['ypos', 'xpos']
                #     }
                for elem, props in elemprop.items():
                    # elem = 'textoverlay_3'
                    # prop = ['xpos']
                    ctlprops = []
                    setprops = []
                    for p in props:
                        if ((elem in control_dict
                             and p in control_dict[elem])):
                            ctlprops += [p]
                        setprops += [p]
                    lmn = self.pipeline.get_by_name(elem)
                    log.debug("element '%s' %s" % (elem, lmn))
                    # create a controller
                    if ctlprops:
                        log.info("ctlprops: %s@%s : %s" %
                                 (elem, ctlprops, ctl))
                        # tmpctl = Gst.Controller(lmn, *ctlprops)
                        for cp in ctlprops:
                            v = lmn.get_property(cp)
                            if not isinstance(v, float):
                                continue
                            tmpctl = GstController.InterpolationControlSource()
                            tmpctl.set_property(
                                'mode', GstController.InterpolationMode.LINEAR)
                            cb = GstController.DirectControlBinding.new(
                                lmn, cp, tmpctl)
                            lmn.add_control_binding(cb)

                            log.debug("%s: %s" % (ctl, v))
                            tmpctl.set(0, v)

                            if ctl not in self.controller:
                                self.controller[ctl] = []
                            self.controller[ctl] += [(tmpctl, ctlprops)]
                    # create setters
                    # (this is just a list so we remember)
                    if setprops:
                        if ctl not in self.setter:
                            self.setter[ctl] = {}
                        if lmn not in self.setter[ctl]:
                            self.setter[ctl][lmn] = []
                        self.setter[ctl][lmn] += setprops

        log.warn("controller: %s" % (self.controller, ))
        log.warn("setter: %s" % (self.setter, ))