Beispiel #1
0
    def __init__(
            self, *,
            node: music.BaseNode, port: node_db.PortDescription,
            parent: Optional[QtWidgets.QWidget],
            **kwargs: Any) -> None:
        super().__init__(node=node, name=port.name, **kwargs)

        self.__node = node
        self.__port = port

        listener = self.__node.port_properties_changed.add(
            self.__portPropertiesChanged)
        self.add_cleanup_function(listener.remove)

        layout = QtWidgets.QHBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        port_properties = self.__node.get_port_properties(self.__port.name)

        if self.__port.WhichOneof('value') == 'float_value':
            self.__dial = control_value_dial.ControlValueDial(parent)
            self.__dial.setDisabled(port_properties.exposed)
            self.__dial.setRange(self.__port.float_value.min, self.__port.float_value.max)
            self.__dial.setDefault(self.__port.float_value.default)
            if self.__port.float_value.scale == node_db.FloatValueDescription.LOG:
                self.__dial.setLogScale(True)
            self.connect(self.__dial.valueChanged, self.__dial.setValue)

            self.__exposed = QtWidgets.QCheckBox(parent)
            self.__exposed.setChecked(port_properties.exposed)
            self.__exposed.toggled.connect(self.__exposedEdited)

            layout.addWidget(self.__exposed)
            layout.addWidget(self.__dial)

        elif self.__port.WhichOneof('value') == 'enum_value':
            self.__enum = ControlValueEnum(parent=parent)
            for item in self.__port.enum_value.items:
                self.__enum.addItem(item.name, item.value)
            self.connect(self.__enum.valueChanged, self.__enum.setValue)

            layout.addWidget(self.__enum)

        layout.addStretch(1)

        self.__widget = QtWidgets.QWidget(parent)
        self.__widget.setLayout(layout)
Beispiel #2
0
    def __updateStepMatrix(self) -> None:
        self.__step_labels.clear()
        self.__current_step = None
        self.__matrix_listeners.cleanup()

        clearLayout(self.__step_layout)

        row = 0
        for col in range(self.__node.num_steps):
            step_label = QtWidgets.QLabel('%d' % (col + 1))
            step_label.setAlignment(Qt.AlignCenter)
            step_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                     QtWidgets.QSizePolicy.Expanding)
            self.__step_layout.addWidget(step_label, row, col + 2)
            self.__step_labels.append(step_label)

        row += 1

        for channel in self.__node.channels:
            channel_layout = QtWidgets.QVBoxLayout()
            channel_layout.setContentsMargins(0, 0, 0, 0)
            channel_layout.setSpacing(0)
            channel_layout.setSizeConstraint(
                QtWidgets.QLayout.SetMinAndMaxSize)

            channel_type = QtWidgets.QComboBox()
            for label, value in [
                ("Value", model_pb2.StepSequencerChannel.VALUE),
                ("Trigger", model_pb2.StepSequencerChannel.TRIGGER),
                ("Gate", model_pb2.StepSequencerChannel.GATE)
            ]:
                channel_type.addItem(label, value)
                if value == channel.type:
                    channel_type.setCurrentIndex(channel_type.count() - 1)
            channel_type.currentIndexChanged.connect(
                functools.partial(self.__channelTypeEdited, channel,
                                  channel_type))
            self.__matrix_listeners.add(
                channel.type_changed.add(
                    functools.partial(self.__channelTypeChanged, channel,
                                      channel_type)))
            channel_layout.addWidget(channel_type)

            if channel.type in (model_pb2.StepSequencerChannel.GATE,
                                model_pb2.StepSequencerChannel.TRIGGER):
                pass

            else:
                assert channel.type == model_pb2.StepSequencerChannel.VALUE

                min_value = QtWidgets.QLineEdit()
                min_value_validator = QtGui.QDoubleValidator()
                min_value_validator.setRange(-100000, 100000, 3)
                min_value.setValidator(min_value_validator)
                min_value.setMinimumWidth(width_for(min_value, "100000") + 8)
                min_value.setText(fmt_value(channel.min_value))
                min_value.editingFinished.connect(
                    functools.partial(self.__channelMinValueEdited, channel,
                                      min_value))
                self.__matrix_listeners.add(
                    channel.min_value_changed.add(
                        functools.partial(self.__channelMinValueChanged,
                                          channel, min_value)))

                max_value = QtWidgets.QLineEdit()
                max_value_validator = QtGui.QDoubleValidator()
                max_value_validator.setRange(-100000, 100000, 3)
                max_value.setValidator(max_value_validator)
                max_value.setMinimumWidth(width_for(max_value, "100000") + 8)
                max_value.setText(fmt_value(channel.max_value))
                max_value.editingFinished.connect(
                    functools.partial(self.__channelMaxValueEdited, channel,
                                      max_value))
                self.__matrix_listeners.add(
                    channel.max_value_changed.add(
                        functools.partial(self.__channelMaxValueChanged,
                                          channel, max_value)))

                log_scale = QtWidgets.QCheckBox()
                log_scale.setChecked(channel.log_scale)
                log_scale.stateChanged.connect(
                    functools.partial(self.__channelLogScaleEdited, channel,
                                      log_scale))
                self.__matrix_listeners.add(
                    channel.log_scale_changed.add(
                        functools.partial(self.__channelLogScaleChanged,
                                          channel, log_scale)))

                l1 = QtWidgets.QHBoxLayout()
                l1.setContentsMargins(0, 0, 0, 0)
                l1.setSpacing(0)
                l1.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
                l3 = QtWidgets.QVBoxLayout()
                l3.setContentsMargins(0, 0, 0, 0)
                l3.setSpacing(0)
                l3.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
                l3.addWidget(QtWidgets.QLabel("min"))
                l3.addWidget(min_value)
                l1.addLayout(l3)
                l4 = QtWidgets.QVBoxLayout()
                l4.setContentsMargins(0, 0, 0, 0)
                l4.setSpacing(0)
                l4.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
                l4.addWidget(QtWidgets.QLabel("max"))
                l4.addWidget(max_value)
                l1.addLayout(l4)
                channel_layout.addLayout(l1)
                l2 = QtWidgets.QHBoxLayout()
                l2.setContentsMargins(0, 0, 0, 0)
                l2.addStretch(1)
                l2.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
                l2.addWidget(log_scale)
                l2.addWidget(QtWidgets.QLabel("log"))
                l2.addStretch(1)
                channel_layout.addLayout(l2)

            channel_layout.addStretch(1)
            self.__step_layout.addLayout(channel_layout, row, 0, 2, 1)

            sep = QtWidgets.QFrame()
            sep.setFrameShape(QtWidgets.QFrame.VLine)
            sep.setFrameShadow(QtWidgets.QFrame.Plain)
            self.__step_layout.addWidget(sep, row, 1, 2, 1)

            for col in range(self.__node.num_steps):
                step = channel.steps[col]

                if channel.type in (model_pb2.StepSequencerChannel.GATE,
                                    model_pb2.StepSequencerChannel.TRIGGER):
                    step_enabled = StepToggle()
                    step_enabled.setChecked(step.enabled)
                    step_enabled.checkedChanged.connect(
                        functools.partial(self.__stepEnabledEdited, step,
                                          step_enabled))
                    self.__matrix_listeners.add(
                        step.enabled_changed.add(
                            functools.partial(self.__stepEnabledChanged, step,
                                              step_enabled)))
                    self.__step_layout.addWidget(step_enabled, row, col + 2)

                else:
                    assert channel.type == model_pb2.StepSequencerChannel.VALUE
                    step_value = control_value_dial.ControlValueDial()
                    step_value.setRange(0.0, 1.0)
                    step_value.setDefault(0.0)
                    step_value.setValue(step.value)
                    step_value.setDisplayFunc(
                        functools.partial(self.__stepValueText, channel))
                    step_value.valueChanged.connect(
                        functools.partial(self.__stepValueEdited, step,
                                          step_value))
                    self.__matrix_listeners.add(
                        step.value_changed.add(
                            functools.partial(self.__stepValueChanged, step,
                                              step_value)))
                    self.__step_layout.addWidget(step_value, row + 1, col + 2)
                    self.__matrix_listeners.add(
                        channel.min_value_changed.add(
                            lambda _, w=step_value: w.update()))
                    self.__matrix_listeners.add(
                        channel.max_value_changed.add(
                            lambda _, w=step_value: w.update()))
                    self.__matrix_listeners.add(
                        channel.log_scale_changed.add(
                            lambda _, w=step_value: w.update()))

            row += 2

        self.__step_layout.setColumnStretch(0, 1)
        self.__step_layout.setColumnStretch(1, 1)
        for col in range(self.__node.num_steps):
            self.__step_layout.setColumnStretch(col + 2, 2)
Beispiel #3
0
    def __init__(self, node: model.Oscilloscope, session_prefix: str,
                 **kwargs: Any) -> None:
        super().__init__(**kwargs)

        self.__node = node

        self.__listeners = core.ListenerMap[str]()
        self.add_cleanup_function(self.__listeners.cleanup)

        self.__listeners[
            'node-messages'] = self.audioproc_client.node_messages.add(
                '%016x' % self.__node.id, self.__nodeMessage)

        label_font = QtGui.QFont(self.font())
        label_font.setPointSizeF(0.8 * label_font.pointSizeF())

        self.__plot = Oscilloscope()

        self.__paused = QtWidgets.QPushButton()
        self.__paused.setCheckable(True)
        self.__paused.setText("Pause")
        self.__paused.toggled.connect(self.__plot.setPaused)

        self.__step = QtWidgets.QPushButton()
        self.__step.setText("Step")
        self.__step.setEnabled(False)
        self.__step.clicked.connect(self.__plot.step)
        self.__paused.toggled.connect(self.__step.setEnabled)

        self.__time_scale = int_dial.IntDial()
        self.__time_scale.setMinimumSize(56, 56)
        self.__time_scale.setRange(-12, 3)
        self.__time_scale.setDefault(-5)
        self.__time_scale.setDisplayFunc(Oscilloscope.formatTimeScale)
        self.__time_scale.valueChanged.connect(self.__plot.setTimeScale)
        self.__time_scale_connector = property_connector.IntDialConnector(
            self.__time_scale,
            self.__node,
            'time_scale',
            mutation_name='%s: Change time scale' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__time_scale_connector.cleanup)

        self.__time_scale_label = QtWidgets.QLabel("Time", self)
        self.__time_scale_label.setFont(label_font)
        self.__time_scale_label.setAlignment(Qt.AlignHCenter)

        self.__hold_time = int_dial.IntDial()
        self.__hold_time.setMinimumSize(56, 56)
        self.__hold_time.setRange(-6, 3)
        self.__hold_time.setDefault(-3)
        self.__hold_time.setDisplayFunc(Oscilloscope.formatHoldTime)
        self.__hold_time.valueChanged.connect(self.__plot.setHoldTime)
        self.__hold_time_connector = property_connector.IntDialConnector(
            self.__hold_time,
            self.__node,
            'hold_time',
            mutation_name='%s: Change hold time' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__hold_time_connector.cleanup)

        self.__hold_time_label = QtWidgets.QLabel("Hold", self)
        self.__hold_time_label.setFont(label_font)
        self.__hold_time_label.setAlignment(Qt.AlignHCenter)

        self.__y_scale = int_dial.IntDial()
        self.__y_scale.setMinimumSize(56, 56)
        self.__y_scale.setRange(-18, 18)
        self.__y_scale.setDefault(1)
        self.__y_scale.setDisplayFunc(Oscilloscope.formatYScale)
        self.__y_scale.valueChanged.connect(self.__plot.setYScale)
        self.__y_scale_connector = property_connector.IntDialConnector(
            self.__y_scale,
            self.__node,
            'y_scale',
            mutation_name='%s: Change Y scale' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__y_scale_connector.cleanup)

        self.__y_scale_label = QtWidgets.QLabel("Y Zoom", self)
        self.__y_scale_label.setFont(label_font)
        self.__y_scale_label.setAlignment(Qt.AlignHCenter)

        self.__y_offset = control_value_dial.ControlValueDial()
        self.__y_offset.setMinimumSize(56, 56)
        self.__y_offset.setRange(-1.0, 1.0)
        self.__y_offset.setDefault(0.0)
        self.__y_offset.valueChanged.connect(self.__plot.setYOffset)
        self.__y_offset_connector = property_connector.ControlValueDialConnector(
            self.__y_offset,
            self.__node,
            'y_offset',
            mutation_name='%s: Change Y offset' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__y_offset_connector.cleanup)

        self.__y_offset_label = QtWidgets.QLabel("Y Off", self)
        self.__y_offset_label.setFont(label_font)
        self.__y_offset_label.setAlignment(Qt.AlignHCenter)

        layout = dynamic_layout.DynamicLayout(
            dynamic_layout.VBox(
                dynamic_layout.Widget(self.__plot, stretch=1),
                dynamic_layout.HBox(
                    dynamic_layout.VBox(
                        dynamic_layout.Widget(self.__paused, priority=5),
                        dynamic_layout.Widget(self.__step, priority=5),
                    ),
                    dynamic_layout.VBox(
                        dynamic_layout.Widget(self.__time_scale, priority=3),
                        dynamic_layout.Widget(self.__time_scale_label,
                                              priority=4),
                        stretch=1,
                    ),
                    dynamic_layout.VBox(
                        dynamic_layout.Widget(self.__hold_time, priority=3),
                        dynamic_layout.Widget(self.__hold_time_label,
                                              priority=4),
                        stretch=1,
                    ),
                    dynamic_layout.VBox(
                        dynamic_layout.Widget(self.__y_scale, priority=3),
                        dynamic_layout.Widget(self.__y_scale_label,
                                              priority=4),
                        stretch=1,
                    ),
                    dynamic_layout.VBox(
                        dynamic_layout.Widget(self.__y_offset, priority=3),
                        dynamic_layout.Widget(self.__y_offset_label,
                                              priority=4),
                        stretch=1,
                    ),
                ),
                spacing=2,
            ))
        self.setLayout(layout)
Beispiel #4
0
    def __init__(self, node: model.StepSequencer, **kwargs: Any) -> None:
        super().__init__(**kwargs)

        self.__node = node
        self.__node.control_value_map.init()

        self.__listeners = core.ListenerMap[str]()
        self.add_cleanup_function(self.__listeners.cleanup)

        self.__listeners[
            'node-messages'] = self.audioproc_client.node_messages.add(
                '%016x' % self.__node.id, self.__nodeMessage)

        body = QtWidgets.QWidget(self)
        body.setAutoFillBackground(False)
        body.setAttribute(Qt.WA_NoSystemBackground, True)

        self.setWidgetResizable(True)
        self.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.setWidget(body)

        tempo_port = self.__node.description.ports[0]
        self.__tempo = control_value_dial.ControlValueDial()
        self.__tempo.setRange(tempo_port.float_value.min,
                              tempo_port.float_value.max)
        self.__tempo.setDefault(tempo_port.float_value.default)
        if tempo_port.float_value.scale == node_db.FloatValueDescription.LOG:
            self.__tempo.setLogScale(True)
        self.__tempo_connector = control_value_connector.ControlValueConnector(
            node=self.__node, name='tempo', context=self.context)
        self.add_cleanup_function(self.__tempo_connector.cleanup)
        self.__tempo_connector.connect(self.__tempo.valueChanged,
                                       self.__tempo.setValue)

        self.__num_steps = QtWidgets.QSpinBox()
        self.__num_steps.setSuffix(" steps")
        self.__num_steps.setKeyboardTracking(False)
        self.__num_steps.setRange(2, 128)
        self.__num_steps.setValue(self.__node.num_steps)
        self.__num_steps.valueChanged.connect(self.__numStepsEdited)
        self.__listeners['num_steps'] = self.__node.num_steps_changed.add(
            self.__numStepsChanged)

        self.__num_channels = QtWidgets.QSpinBox()
        self.__num_channels.setSuffix(" channels")
        self.__num_channels.setKeyboardTracking(False)
        self.__num_channels.setRange(1, 100)
        self.__num_channels.setValue(len(self.__node.channels))
        self.__num_channels.valueChanged.connect(self.__numChannelsEdited)
        self.__listeners['num_channels'] = self.__node.channels_changed.add(
            self.__numChannelsChanged)

        self.__step_layout = QtWidgets.QGridLayout()
        self.__step_layout.setVerticalSpacing(5)
        self.__step_layout.setHorizontalSpacing(10)
        self.__step_layout.setSizeConstraint(
            QtWidgets.QLayout.SetMinAndMaxSize)
        self.__current_step = None  # type: QtWidgets.QLabel
        self.__step_labels = []  # type: List[QtWidgets.QLabel]
        self.__matrix_listeners = core.ListenerList()
        self.add_cleanup_function(self.__matrix_listeners.cleanup)
        self.__updateStepMatrix()

        body_layout = QtWidgets.QVBoxLayout()
        l1 = QtWidgets.QHBoxLayout()
        l1.addWidget(self.__tempo)
        l1.addWidget(self.__num_steps)
        l1.addWidget(self.__num_channels)
        l1.addStretch(1)
        body_layout.addLayout(l1)
        body_layout.addLayout(self.__step_layout)
        body_layout.addStretch(1)
        body.setLayout(body_layout)
Beispiel #5
0
    def __init__(self, channel: model.MidiCCtoCVChannel, **kwargs: Any) -> None:
        super().__init__(**kwargs)

        self.__channel = channel
        self.__node = cast(model.MidiCCtoCV, channel.parent)

        self.__listeners = core.ListenerMap[str]()
        self.add_cleanup_function(self.__listeners.cleanup)
        self.__learning = False

        self.__midi_channel = MidiChannelSpinBox()
        self.__midi_channel.setObjectName('channel[%016x]:midi_channel' % channel.id)
        self.__midi_channel.setKeyboardTracking(False)
        self.__midi_channel.setRange(0, 15)
        self.__midi_channel_connector = property_connector.QSpinBoxConnector(
            self.__midi_channel, self.__channel, 'midi_channel',
            mutation_name='%s: Change MIDI channel' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__midi_channel_connector.cleanup)

        self.__midi_controller = QtWidgets.QSpinBox()
        self.__midi_controller.setObjectName('channel[%016x]:midi_controller' % channel.id)
        self.__midi_controller.setRange(0, 127)
        self.__midi_controller_connector = property_connector.QSpinBoxConnector(
            self.__midi_controller, self.__channel, 'midi_controller',
            mutation_name='%s: Change MIDI controller' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__midi_controller_connector.cleanup)

        self.__learn_timeout = QtCore.QTimer()
        self.__learn_timeout.setInterval(5000)
        self.__learn_timeout.setSingleShot(True)
        self.__learn_timeout.timeout.connect(self.__learnStop)

        self.__learn = LearnButton()
        self.__learn.setObjectName('channel[%016x]:learn' % channel.id)
        self.__learn.toggled.connect(self.__learnClicked)

        self.__min_value = QtWidgets.QLineEdit()
        self.__min_value.setObjectName('channel[%016x]:min_value' % channel.id)
        min_value_validator = QtGui.QDoubleValidator()
        min_value_validator.setRange(-100000, 100000, 3)
        self.__min_value.setValidator(min_value_validator)
        self.__min_value_connector = property_connector.QLineEditConnector[float](
            self.__min_value, self.__channel, 'min_value',
            mutation_name='%s: Change min. value' % self.__node.name,
            parse_func=float,
            display_func=fmt_value,
            context=self.context)
        self.add_cleanup_function(self.__min_value_connector.cleanup)

        self.__max_value = QtWidgets.QLineEdit()
        self.__max_value.setObjectName('channel[%016x]:max_value' % channel.id)
        max_value_validator = QtGui.QDoubleValidator()
        max_value_validator.setRange(-100000, 100000, 3)
        self.__max_value.setValidator(max_value_validator)
        self.__max_value_connector = property_connector.QLineEditConnector[float](
            self.__max_value, self.__channel, 'max_value',
            mutation_name='%s: Change max. value' % self.__node.name,
            parse_func=float,
            display_func=fmt_value,
            context=self.context)
        self.add_cleanup_function(self.__max_value_connector.cleanup)

        self.__log_scale = QtWidgets.QCheckBox()
        self.__log_scale.setObjectName('channel[%016x]:log_scale' % channel.id)
        self.__log_scale_connector = property_connector.QCheckBoxConnector(
            self.__log_scale, self.__channel, 'log_scale',
            mutation_name='%s: Change log scale' % self.__node.name,
            context=self.context)
        self.add_cleanup_function(self.__log_scale_connector.cleanup)

        self.__current_value = control_value_dial.ControlValueDial()
        self.__current_value.setRange(0.0, 1.0)
        self.__current_value.setReadOnly(True)