Пример #1
0
    def buildMixer(self):
        #print self.hw
        #print self.hw.getText("/Generic/Nickname")
        self.mixer = MatrixMixer(self.hw.servername, self.hw.basepath+"/EAP/MatrixMixer", self, "Columns_are_outputs", -1, None, None, False, QTabWidget.North, QTabWidget.Rounded)
        self.tabs.addTab(self.mixer, "Mixer")

        self.router_scrollarea = self.buildRouter(self.hw.servername, self.hw.basepath+"/EAP/Router")
        self.tabs.addTab(self.router_scrollarea, "Crossbar Router")
Пример #2
0
    def buildMixer(self):
        #print( self.hw )
        #print( self.hw.getText("/Generic/Nickname") )
        self.mixer = MatrixMixer(self.hw.servername, self.hw.basepath+"/EAP/MatrixMixer", self, "Columns_are_outputs", -1, None, None, False, QTabWidget.North, QTabWidget.Rounded)
        self.tabs.addTab(self.mixer, "Mixer")

        self.router_scrollarea = self.buildRouter(self.hw.servername, self.hw.basepath+"/EAP/Router")
        self.tabs.addTab(self.router_scrollarea, "Crossbar Router")
Пример #3
0
    def buildMixer(self):
        #print self.hw
        #print self.hw.getText("/Generic/Nickname")
        self.matrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/EAP/MatrixMixer", self)
        scrollarea = QtGui.QScrollArea(self.tabs)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.matrix)
        self.tabs.addTab(scrollarea, "Matrix")

        self.router = CrossbarRouter(self.hw.servername, self.hw.basepath+"/EAP/Router", self)
        scrollarea = QtGui.QScrollArea(self.tabs)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.router)
        self.tabs.addTab(scrollarea, "Routing")

        model = MonitoringModel(self.hw, self)

        widget = QtGui.QWidget()
        uicLoad("ffado/mixer/saffire_dice_monitoring.ui", widget)
        widget.monitoringView.setModel(model)
        widget.monitoringView.setItemDelegate(MonitoringDelegate(self))
        self.tabs.addTab(widget, "Monitoring")

        self.muteInterface = BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalMute/State")
        widget.btnMute.setChecked(self.muteInterface.selected())
        self.connect(widget.btnMute, QtCore.SIGNAL("toggled(bool)"), self.muteToggle)
        self.dimInterface = BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalDim/State")
        widget.btnDim.setChecked(self.dimInterface.selected())
        self.connect(widget.btnDim, QtCore.SIGNAL("toggled(bool)"), self.dimToggle)

        self.dimLevelInterface = DiscreteControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalDim/Level")
        widget.dimLevel.setValue(self.dimLevelInterface.getvalue())
        self.connect(widget.dimLevel, QtCore.SIGNAL("valueChanged(int)"), self.dimLevelChanged)
        self.volumeInterface = DiscreteControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalVolume/Level")
        widget.volumeKnob.setValue(self.volumeInterface.getvalue())
        self.connect(widget.volumeKnob, QtCore.SIGNAL("valueChanged(int)"), self.volumeChanged)

        if self.configrom.getModelName() == "SAFFIRE_PRO_24":
            self.ch1inst = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch1LineInst")
            widget.chkInst1.setChecked(self.ch1inst.selected())
            self.connect(widget.chkInst1, QtCore.SIGNAL("toggled(bool)"), self.ch1inst.select)
            self.ch2inst = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch2LineInst")
            widget.chkInst2.setChecked(self.ch2inst.selected())
            self.connect(widget.chkInst2, QtCore.SIGNAL("toggled(bool)"), self.ch2inst.select)
            self.ch3level = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch3Level")
            widget.chkLevel3.setChecked(self.ch3level.selected())
            self.connect(widget.chkLevel3, QtCore.SIGNAL("toggled(bool)"), self.ch3level.select)
            self.ch4level = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch4Level")
            widget.chkLevel4.setChecked(self.ch4level.selected())
            self.connect(widget.chkLevel4, QtCore.SIGNAL("toggled(bool)"), self.ch4level.select)
        else:
            widget.chkInst1.deleteLater()
            widget.chkInst2.deleteLater()
            widget.chkLevel3.deleteLater()
            widget.chkLevel4.deleteLater()
Пример #4
0
    def buildMixer(self):
        #print self.hw
        #print self.hw.getText("/Generic/Nickname")
        self.matrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/EAP/MatrixMixer", self)
        scrollarea = QtGui.QScrollArea(self.tabs)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.matrix)
        self.tabs.addTab(scrollarea, "Matrix Mixer")

        self.router = CrossbarRouter(self.hw.servername, self.hw.basepath+"/EAP/Router", self)
        scrollarea = QtGui.QScrollArea(self.tabs)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.router)
        self.tabs.addTab(scrollarea, "Crossbar Router")
Пример #5
0
    def initValues(self):

        # print self.hw.servername
        # print self.hw.basepath
        self.inputmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/InputFaders", self,
            "Columns_are_inputs", 0x8000,
            self.hw.basepath + "/Mixer/InputMutes",
            self.hw.basepath + "/Mixer/InputInverts", True)
        layout = QVBoxLayout()
        layout.addWidget(self.inputmatrix)
        self.mixer.setLayout(layout)

        self.playbackmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/PlaybackFaders",
            self, "Columns_are_inputs", 0x8000,
            self.hw.basepath + "/Mixer/PlaybackMutes",
            self.hw.basepath + "/Mixer/PlaybackInverts", True)
        layout = QVBoxLayout()
        layout.addWidget(self.playbackmatrix)
        self.playbackmixer.setLayout(layout)

        self.outputmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/OutputFaders", self,
            "Columns_are_inputs", 0x8000,
            self.hw.basepath + "/Mixer/OutputMutes", None, True)
        layout = QVBoxLayout()

        # This is a bit of a hack, but it works to ensure this single-row
        # matrix mixer doesn't fill the entire screen but also doesn't end
        # up with a pointless scrollbar.  The matrix mixer's minimum height
        # is 0 according to minimumHeight(), which is probably the
        # fundamental issue here; however, I've already wasted too much time
        # trying to get this to work so if the hack is effective we'll run
        # with it.
        self.outputmatrix.setMinimumHeight(150)
        layout.addWidget(self.outputmatrix, 0, Qt.AlignTop)
        self.outputmixer.setLayout(layout)

        self.is_streaming = False
        self.last_streaming_state = False

        # Disable the "load settings" button if streaming is active.  Its
        # enable state will be kept up to date by updateStreamingState().
        self.control_load.setEnabled(not (self.is_streaming))

        # Also disable other controls which are not yet implemented.
        self.mixer_preset_ffado_default.setEnabled(False)

        # Retrieve other device settings as needed and customise the UI
        # based on these options.
        self.model = self.hw.getDiscrete('/Control/Model')
        log.debug("device model identifier: %d" % (self.model))
        self.tco_present = self.hw.getDiscrete('/Control/TCO_present')
        log.debug("device has TCO: %d" % (self.tco_present))
        #self.sample_rate = self.hw.getDiscrete('/Mixer/Info/SampleRate')
        #log.debug("device sample rate: %d" % (self.sample_rate))

        # Assume the TCO options tab is the second from the left (index 1)
        if (not (self.tco_present)):
            self.disable_hide(self.tco_options)
            self.tabWidget.setTabEnabled(1, False)
            self.tabWidget.removeTab(1)

        # The Fireface-400 only has 2 phantom-capable channels
        if (self.model == RME_MODEL_FF400):
            self.disable_hide(self.phantom_2)
            self.disable_hide(self.phantom_3)
        else:
            self.phantom_0.setText("Mic 7")
            self.phantom_1.setText("Mic 8")
            self.phantom_2.setText("Mic 9")
            self.phantom_3.setText("Mic 10")

        # Instrument options, input jack selection controls and an ADAT2
        # input are applicable only to the FF800
        if (self.model != RME_MODEL_FF800):
            self.instrument_options_group.setEnabled(False)
            self.input_plug_select_group.setEnabled(False)
            self.sync_ref_adat2.setEnabled(False)
            self.sync_check_adat2_label.setEnabled(False)
            self.sync_check_adat2_status.setEnabled(False)
            self.spdif_output_optical.setText("ADAT optical")
            self.spdif_input_optical.setText("ADAT optical")

        if (not (self.tco_present)):
            self.sync_check_tco_label.setEnabled(False)
            self.sync_check_tco_status.setEnabled(False)
            self.sync_ref_tco.setEnabled(False)

        # Only the FF400 has specific channel 3/4 options, input gain
        # controls and switchable phones level
        if (self.model != RME_MODEL_FF400):
            # Hide the upper-level frame (and everything in it) to ensure it
            # requests no vertical space when its contents aren't needed.
            self.disable_hide(self.igains_chan34_opts_frame)
            self.phones_level_group.setEnabled(False)

        # Add the "No ADAT-2" item to the bandwidth limit control if the
        # device is not a FF400.
        if (self.model != RME_MODEL_FF400):
            self.bandwidth_limit.insertItem(1, "No ADAT-2")

        self.getValuesFromFF()
        self.setupSignals()

        # Ensure the limiter checkbox has a signal handler associated with
        # it.  If getValuesFromFF() disabled it because the front input was
        # not selected, setupSignals() would not have configured a handler.
        if (not (self.ch1_instr_limiter.isEnabled())):
            self.ch1_instr_limiter.toggled.connect(self.updateCheckboxes)

        self.updateStreamingState()
        #log.debug("device streaming flag: %d" % (self.is_streaming))

        self.update_timer = QTimer(self)
        self.update_timer.timeout.connect(self.status_update)
        self.update_timer.start(1000)
Пример #6
0
class Rme(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        uicLoad("ffado/mixer/rme", self)

        self.init()

    def init(self):

        self.PhantomSwitches = {
            self.phantom_0: ['/Control/Phantom', 0],
            self.phantom_1: ['/Control/Phantom', 1],
            self.phantom_2: ['/Control/Phantom', 2],
            self.phantom_3: ['/Control/Phantom', 3],
        }

        self.Switches = {
            self.ff400_chan3_opt_instr: ['/Control/Chan3_opt_instr'],
            self.ff400_chan3_opt_pad: ['/Control/Chan3_opt_pad'],
            self.ff400_chan4_opt_instr: ['/Control/Chan4_opt_instr'],
            self.ff400_chan4_opt_pad: ['/Control/Chan4_opt_pad'],
            self.spdif_output_optical: ['/Control/SPDIF_output_optical', 0],
            self.spdif_output_emphasis: ['/Control/SPDIF_output_emphasis', 0],
            self.spdif_output_pro: ['/Control/SPDIF_output_pro', 0],
            self.spdif_output_nonaudio: ['/Control/SPDIF_output_nonaudio', 0],
        }

        self.Radiobuttons = {
            self.level_in_lo_gain: ['/Control/Input_level', 0],
            self.level_in_p4dBu: ['/Control/Input_level', 2],
            self.level_in_m10dBV: ['/Control/Input_level', 1],
            self.level_out_hi_gain: ['/Control/Output_level', 2],
            self.level_out_p4dBu: ['/Control/Output_level', 1],
            self.level_out_m10dBV: ['/Control/Output_level', 0],
            self.spdif_input_coax: ['/Control/SPDIF_input_mode', 0],
            self.spdif_input_optical: ['/Control/SPDIF_input_mode', 1],
            self.phones_hi_gain: ['/Control/Phones_level', 0],
            self.phones_p4dBu: ['/Control/Phones_level', 1],
            self.phones_m10dBV: ['/Control/Phones_level', 2],
            self.clock_mode_autosync: ['/Control/Clock_mode', 1],
            self.clock_mode_master: ['/Control/Clock_mode', 0],
            self.sync_ref_wordclk: ['/Control/Sync_ref', 0],
            self.sync_ref_adat1: ['/Control/Sync_ref', 1],
            self.sync_ref_adat2: ['/Control/Sync_ref', 2],
            self.sync_ref_spdif: ['/Control/Sync_ref', 3],
            self.sync_ref_tco: ['/Control/Sync_ref', 4],

            # TCO controls
            self.sync_source_ltc: ['/Control/Tco_sync_src', 0],
            self.sync_source_video: ['/Control/Tco_sync_src', 1],
            self.sync_source_wordclk: ['/Control/Tco_sync_src', 2],
            self.frame_rate_24fps: ['/Control/Tco_frame_rate', 0],
            self.frame_rate_25fps: ['/Control/Tco_frame_rate', 1],
            self.frame_rate_29_97fps: ['/Control/Tco_frame_rate', 2],
            self.frame_rate_29_97dfps: ['/Control/Tco_frame_rate', 3],
            self.frame_rate_30fps: ['/Control/Tco_frame_rate', 4],
            self.frame_rate_30dfps: ['/Control/Tco_frame_rate', 5],
            self.sample_rate_44k1: ['/Control/Tco_sample_rate', 0],
            self.sample_rate_48k: ['/Control/Tco_sample_rate', 1],
            self.sample_rate_0pc: ['/Control/Tco_sample_rate_ofs', 0],
            self.sample_rate_p01pc: ['/Control/Tco_sample_rate_ofs', 1],
            self.sample_rate_n01pc: ['/Control/Tco_sample_rate_ofs', 2],
            self.sample_rate_p40pc: ['/Control/Tco_sample_rate_ofs', 3],
            self.sample_rate_n40pc: ['/Control/Tco_sample_rate_ofs', 4],
            self.wordclk_conv_1_1: ['/Control/Tco_word_clk_conv', 0],
            self.wordclk_conv_44k1_48k: ['/Control/Tco_word_clk_conv', 1],
            self.wordclk_conv_48k_44k1: ['/Control/Tco_word_clk_conv', 2],
        }

        self.Checkboxes = {
            self.ch1_instr_fuzz: ['/Control/Chan1_instr_opts', 0x04],
            self.ch1_instr_limiter: ['/Control/Chan1_instr_opts', 0x08],
            self.ch1_instr_filter: ['/Control/Chan1_instr_opts', 0x02],

            # TCO controls
            self.video_input_termination_on:
            ['/Control/Tco_video_in_term', 0x01],
        }

        self.Gains = {
            self.gain_mic1: ['/Control/Gains', 0],
            self.gain_mic2: ['/Control/Gains', 1],
            self.gain_input3: ['/Control/Gains', 2],
            self.gain_input4: ['/Control/Gains', 3],
        }

        self.Combos = {
            self.ff800_ch1_src: ['/Control/Chan1_source'],
            self.ff800_ch7_src: ['/Control/Chan7_source'],
            self.ff800_ch8_src: ['/Control/Chan8_source'],
        }

        self.CommandButtons = {
            self.control_load: ['/Control/Flash_control', 0],
            self.control_save: ['/Control/Flash_control', 1],
            self.mixer_load: ['/Control/Flash_control', 2],
            self.mixer_save: ['/Control/Flash_control', 3],
            self.mixer_preset_ffado_default: ['/Control/Mixer_preset', 0],
        }

        # Other mixer variables
        self.is_streaming = 0
        self.sample_rate = 0
        self.model = 0
        self.tco_present = 0

    # Public slot: update phantom power hardware switches
    def updatePhantomSwitch(self, a0):
        sender = self.sender()
        # Value is the phantom switch value, with a corresponding enable
        # bit in the high 16 bit word
        val = (a0 << self.PhantomSwitches[sender][1]) | (
            0x00010000 << self.PhantomSwitches[sender][1])
        log.debug("phantom switch %d set to %d" %
                  (self.PhantomSwitches[sender][1], a0))
        self.hw.setDiscrete(self.PhantomSwitches[sender][0], val)

    # Public slot: update generic switches
    def updateSwitch(self, a0):
        sender = self.sender()
        log.debug("switch %s set to %d" % (self.Switches[sender][0], a0))
        self.hw.setDiscrete(self.Switches[sender][0], a0)

    # Public slot: update generic radiobuttons
    def updateRadiobutton(self, a0):
        sender = self.sender()
        if (a0 != 0):
            # Only change the control state on a button being "checked"
            log.debug(
                "radiobutton group %s set to %d" %
                (self.Radiobuttons[sender][0], self.Radiobuttons[sender][1]))
            self.hw.setDiscrete(self.Radiobuttons[sender][0],
                                self.Radiobuttons[sender][1])

    def updateCheckboxes(self, a0):
        sender = self.sender()
        val = self.hw.getDiscrete(self.Checkboxes[sender][0])
        if (a0 != 0):
            val = val | self.Checkboxes[sender][1]
        else:
            val = val & ~self.Checkboxes[sender][1]
        log.debug("checkbox group %s set to %d" %
                  (self.Checkboxes[sender][0], val))
        self.hw.setDiscrete(self.Checkboxes[sender][0], val)

    # Public slot: update gains
    def updateGain(self, a0):
        sender = self.sender()
        log.debug("gain %s[%d] set to %d" %
                  (self.Gains[sender][0], self.Gains[sender][1], a0))
        self.hw.setMatrixMixerValue(self.Gains[sender][0], 0,
                                    self.Gains[sender][1], a0)

    def updateBandwidthLimit(self, a0):
        # Account for the "No ADAT-2" item which will not be present on
        # a FF400.
        if (self.model == RME_MODEL_FF400 and a0 > 0):
            a0 = a0 + 1
        # log.debug("limit update: %d" % (a0));
        self.hw.setDiscrete('/Control/Bandwidth_limit', a0)

    # Public slot: send command
    def sendCommand(self, a0):
        sender = self.sender()
        log.debug(
            "command %d sent to %s" %
            (self.CommandButtons[sender][1], self.CommandButtons[sender][0]))
        self.hw.setDiscrete(self.CommandButtons[sender][0],
                            self.CommandButtons[sender][1])

        # If mixer values have been reloaded, refresh the mixer GUI.  This
        # will also commit the new values to the hardware via the "changed"
        # signal handlers of the mixer elements.
        if (self.CommandButtons[sender][1] == 2):
            self.inputmatrix.refreshValues()
            self.outputmatrix.refreshValues()
            self.playbackmatrix.refreshValues()

        # If settings have been reloaded from flash, refresh the GUI.  The
        # settings will be made active in the hardware via the "changed"
        # signal handlers of the respective GUI control widgets.
        if (self.CommandButtons[sender][1] == 0):
            self.getValuesFromFF()

    def updateCombo(self, a0):
        sender = self.sender()
        log.debug("combo %s set to %d" % (self.Combos[sender][0], a0))
        self.hw.setDiscrete(self.Combos[sender][0], a0)

        # Enable the limiter control only when the front source is active
        if (sender == self.ff800_ch1_src):
            self.ch1_instr_limiter.setEnabled(a0 == 0)

    def updateStreamingState(self):
        ss = self.streamingstatus.selected()
        ss_txt = self.streamingstatus.getEnumLabel(ss)
        if ss_txt != 'Idle':
            self.is_streaming = True
        else:
            self.is_streaming = False
        if (self.last_streaming_state != self.is_streaming):
            self.bandwidth_limit.setEnabled(not (self.is_streaming))
            self.control_load.setEnabled(not (self.is_streaming))
        self.last_streaming_state = self.is_streaming

    def status_update(self):
        # log.debug("timer event")
        self.updateStreamingState()
        clk_mode = ['Master', 'Slave']
        src_str = ['None', 'ADAT 1', 'ADAT 2', 'SPDIF', 'Wordclock', 'TCO']
        sync_stat = ['No lock', 'Locked', 'Synced']
        sysclock_mode = self.hw.getDiscrete('/Control/sysclock_mode')
        sysclock_freq = self.hw.getDiscrete('/Control/sysclock_freq')
        autosync_freq = self.hw.getDiscrete('/Control/autosync_freq')
        autosync_src = self.hw.getDiscrete('/Control/autosync_src')
        sync_status = self.hw.getDiscrete('/Control/sync_status')
        spdif_freq = self.hw.getDiscrete('/Control/spdif_freq')
        self.sysclock_freq.setText("%d Hz" % (sysclock_freq))
        self.sysclock_mode.setText(clk_mode[sysclock_mode])
        self.autosync_freq.setText("%d Hz" % (autosync_freq))
        self.autosync_src.setText(src_str[autosync_src])
        self.sync_check_adat1_status.setText(sync_stat[sync_status & 0x03])
        self.sync_check_adat2_status.setText(sync_stat[(sync_status >> 2)
                                                       & 0x03])
        self.sync_check_spdif_status.setText(sync_stat[(sync_status >> 4)
                                                       & 0x03])
        self.sync_check_wclk_status.setText(sync_stat[(sync_status >> 6)
                                                      & 0x03])
        self.sync_check_tco_status.setText(sync_stat[(sync_status >> 8)
                                                     & 0x03])
        self.spdif_freq.setText("%d Hz" % (spdif_freq))

        if (self.tco_present):
            ltc_valid_str = ['Not detected', 'Valid']
            ltc_framerate_str = ['24 fps', '25 fps', '29.97 fps', '30 fps']
            ltc_frametype_str = ['Normal (full frame)', 'Dropframe']
            video_type_str = ['No video', 'PAL', 'NTSC']
            word_clock_str = [
                'None', 'Single Speed', 'Double Speed', 'Quad Speed'
            ]
            status_str = ['Not locked', "Locked"]
            ltc = self.hw.getDiscrete('/Control/Tco_ltc_in')
            ltc_valid = self.hw.getDiscrete('/Control/Tco_input_ltc_valid')
            ltc_fps = self.hw.getDiscrete('/Control/Tco_input_ltc_fps')
            ltc_dropframe = self.hw.getDiscrete(
                '/Control/Tco_input_ltc_dropframe')
            videotype = self.hw.getDiscrete('/Control/Tco_input_video_type')
            wordclk = self.hw.getDiscrete('/Control/Tco_input_word_clk')
            input_lock = self.hw.getDiscrete('/Control/Tco_input_lock')
            tco_freq = self.hw.getDiscrete('/Control/Tco_freq')
            self.state_ltc_valid_label.setText(ltc_valid_str[ltc_valid])
            if (ltc_valid):
                self.ltc_in_hours.setText("%02d" % (ltc >> 24))
                self.ltc_in_minutes.setText("%02d" % ((ltc >> 16) & 0xff))
                self.ltc_in_seconds.setText("%02d" % ((ltc >> 8) & 0xff))
                self.ltc_in_frames.setText("%02d" % (ltc & 0xff))
                self.state_ltc_framerate.setText(ltc_framerate_str[ltc_fps])
                self.state_ltc_frame_type.setText(
                    ltc_frametype_str[ltc_dropframe])
            else:
                self.ltc_in_hours.setText("--")
                self.ltc_in_minutes.setText("--")
                self.ltc_in_seconds.setText("--")
                self.ltc_in_frames.setText("--")
                self.state_ltc_framerate.setText("-")
                self.state_ltc_frame_type.setText("-")
            self.state_video_type.setText(video_type_str[videotype])
            self.state_word_clk.setText(word_clock_str[wordclk])
            self.sync_source_status.setText(status_str[input_lock])
            self.tco_frequency_label.setText("%d Hz" % (tco_freq))

    # Hide and disable a control
    def disable_hide(self, widget):
        for w in widget.children():
            if isinstance(w, QWidget):
                w.hide()
                w.setEnabled(False)
        widget.hide()
        widget.setEnabled(False)

    def setupSignals(self):

        # Connect signal handlers for all command buttons
        for ctrl, info in self.CommandButtons.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.clicked.connect(self.sendCommand)

        for ctrl, info in self.Combos.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.currentIndexChanged.connect(self.updateCombo)

        self.bandwidth_limit.currentIndexChanged.connect(
            self.updateBandwidthLimit)

        # Get current hardware values and connect GUI element signals to
        # their respective slots
        for ctrl, info in self.PhantomSwitches.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.toggled.connect(self.updatePhantomSwitch)

        for ctrl, info in self.Switches.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.toggled.connect(self.updateSwitch)

        for ctrl, info in self.Radiobuttons.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.toggled.connect(self.updateRadiobutton)

        for ctrl, info in self.Checkboxes.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.toggled.connect(self.updateCheckboxes)

        for ctrl, info in self.Gains.items():
            if (not (ctrl.isEnabled())):
                continue
            ctrl.valueChanged.connect(self.updateGain)

    # Obtain control values from the Fireface and make the GUI reflect these
    def getValuesFromFF(self):
        for ctrl, info in self.Combos.items():
            if (not (ctrl.isEnabled())):
                continue
            val = self.hw.getDiscrete(info[0])
            log.debug("combo %s is %d" % (info[0], val))
            ctrl.setCurrentIndex(val)

        # Set the bandwidth limit control to reflect the current device
        # setting, allowing for the additional "No ADAT-2" item which is
        # present on the FF800.
        val = self.hw.getDiscrete('/Control/Bandwidth_limit')
        if (self.model == RME_MODEL_FF400 and val > 1):
            val = val - 1
        self.bandwidth_limit.setCurrentIndex(val)

        # Get current hardware values
        for ctrl, info in self.PhantomSwitches.items():
            if (not (ctrl.isEnabled())):
                continue
            val = (self.hw.getDiscrete(info[0]) >> info[1]) & 0x01
            log.debug("phantom switch %d is %d" % (info[1], val))
            if val:
                ctrl.setChecked(True)
            else:
                ctrl.setChecked(False)

        for ctrl, info in self.Switches.items():
            if (not (ctrl.isEnabled())):
                continue
            val = self.hw.getDiscrete(info[0])
            log.debug("switch %s is %d" % (info[0], val))
            if val:
                ctrl.setChecked(True)
            else:
                ctrl.setChecked(False)

        for ctrl, info in self.Radiobuttons.items():
            if (not (ctrl.isEnabled())):
                continue
            # This is a touch wasteful since it means we retrieve the control
            # value once per radio button rather than once per radio button
            # group.  In time we might introduce radiobutton groupings in the
            # self.* datastructures to avoid this, but for the moment this is
            # easy and it works.
            val = self.hw.getDiscrete(info[0])
            if (val == info[1]):
                val = 1
            else:
                val = 0
            ctrl.setChecked(val)
            log.debug("Radiobutton %s[%d] is %d" % (info[0], info[1], val))

        # Make sure the Limiter control can receive a value
        if (self.ff800_ch1_src.isEnabled()):
            self.ch1_instr_limiter.setEnabled(1)

        for ctrl, info in self.Checkboxes.items():
            if (not (ctrl.isEnabled())):
                continue
            # This is a touch wasteful since it means we retrieve the control
            # value once per checkbox button rather than once per checkbox
            # group.  In time we might introduce checkbox groupings in the
            # self.* datastructures to avoid this, but for the moment this is
            # easy and it works.
            val = self.hw.getDiscrete(info[0])
            if (val & info[1]):
                val = 1
            else:
                val = 0
            ctrl.setChecked(val)
            log.debug("Checkbox %s[%d] is %d" % (info[0], info[1], val))

        # The limiter (a checkbox) can only be controlled if the front
        # source is selected for channel 1.
        ch1_src = self.ff800_ch1_src.currentIndex()
        if (self.ff800_ch1_src.isEnabled()):
            self.ch1_instr_limiter.setEnabled(ch1_src == 0)

        for ctrl, info in self.Gains.items():
            if (not (ctrl.isEnabled())):
                continue
            val = self.hw.getMatrixMixerValue(info[0], 0, info[1])
            log.debug("gain %s[%d] is %d" % (info[0], info[1], val))
            ctrl.setValue(val)

    def initValues(self):

        # print self.hw.servername
        # print self.hw.basepath
        self.inputmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/InputFaders", self,
            "Columns_are_inputs", 0x8000,
            self.hw.basepath + "/Mixer/InputMutes",
            self.hw.basepath + "/Mixer/InputInverts", True)
        layout = QVBoxLayout()
        layout.addWidget(self.inputmatrix)
        self.mixer.setLayout(layout)

        self.playbackmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/PlaybackFaders",
            self, "Columns_are_inputs", 0x8000,
            self.hw.basepath + "/Mixer/PlaybackMutes",
            self.hw.basepath + "/Mixer/PlaybackInverts", True)
        layout = QVBoxLayout()
        layout.addWidget(self.playbackmatrix)
        self.playbackmixer.setLayout(layout)

        self.outputmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/OutputFaders", self,
            "Columns_are_inputs", 0x8000,
            self.hw.basepath + "/Mixer/OutputMutes", None, True)
        layout = QVBoxLayout()

        # This is a bit of a hack, but it works to ensure this single-row
        # matrix mixer doesn't fill the entire screen but also doesn't end
        # up with a pointless scrollbar.  The matrix mixer's minimum height
        # is 0 according to minimumHeight(), which is probably the
        # fundamental issue here; however, I've already wasted too much time
        # trying to get this to work so if the hack is effective we'll run
        # with it.
        self.outputmatrix.setMinimumHeight(150)
        layout.addWidget(self.outputmatrix, 0, Qt.AlignTop)
        self.outputmixer.setLayout(layout)

        self.is_streaming = False
        self.last_streaming_state = False

        # Disable the "load settings" button if streaming is active.  Its
        # enable state will be kept up to date by updateStreamingState().
        self.control_load.setEnabled(not (self.is_streaming))

        # Also disable other controls which are not yet implemented.
        self.mixer_preset_ffado_default.setEnabled(False)

        # Retrieve other device settings as needed and customise the UI
        # based on these options.
        self.model = self.hw.getDiscrete('/Control/Model')
        log.debug("device model identifier: %d" % (self.model))
        self.tco_present = self.hw.getDiscrete('/Control/TCO_present')
        log.debug("device has TCO: %d" % (self.tco_present))
        #self.sample_rate = self.hw.getDiscrete('/Mixer/Info/SampleRate')
        #log.debug("device sample rate: %d" % (self.sample_rate))

        # Assume the TCO options tab is the second from the left (index 1)
        if (not (self.tco_present)):
            self.disable_hide(self.tco_options)
            self.tabWidget.setTabEnabled(1, False)
            self.tabWidget.removeTab(1)

        # The Fireface-400 only has 2 phantom-capable channels
        if (self.model == RME_MODEL_FF400):
            self.disable_hide(self.phantom_2)
            self.disable_hide(self.phantom_3)
        else:
            self.phantom_0.setText("Mic 7")
            self.phantom_1.setText("Mic 8")
            self.phantom_2.setText("Mic 9")
            self.phantom_3.setText("Mic 10")

        # Instrument options, input jack selection controls and an ADAT2
        # input are applicable only to the FF800
        if (self.model != RME_MODEL_FF800):
            self.instrument_options_group.setEnabled(False)
            self.input_plug_select_group.setEnabled(False)
            self.sync_ref_adat2.setEnabled(False)
            self.sync_check_adat2_label.setEnabled(False)
            self.sync_check_adat2_status.setEnabled(False)
            self.spdif_output_optical.setText("ADAT optical")
            self.spdif_input_optical.setText("ADAT optical")

        if (not (self.tco_present)):
            self.sync_check_tco_label.setEnabled(False)
            self.sync_check_tco_status.setEnabled(False)
            self.sync_ref_tco.setEnabled(False)

        # Only the FF400 has specific channel 3/4 options, input gain
        # controls and switchable phones level
        if (self.model != RME_MODEL_FF400):
            # Hide the upper-level frame (and everything in it) to ensure it
            # requests no vertical space when its contents aren't needed.
            self.disable_hide(self.igains_chan34_opts_frame)
            self.phones_level_group.setEnabled(False)

        # Add the "No ADAT-2" item to the bandwidth limit control if the
        # device is not a FF400.
        if (self.model != RME_MODEL_FF400):
            self.bandwidth_limit.insertItem(1, "No ADAT-2")

        self.getValuesFromFF()
        self.setupSignals()

        # Ensure the limiter checkbox has a signal handler associated with
        # it.  If getValuesFromFF() disabled it because the front input was
        # not selected, setupSignals() would not have configured a handler.
        if (not (self.ch1_instr_limiter.isEnabled())):
            self.ch1_instr_limiter.toggled.connect(self.updateCheckboxes)

        self.updateStreamingState()
        #log.debug("device streaming flag: %d" % (self.is_streaming))

        self.update_timer = QTimer(self)
        self.update_timer.timeout.connect(self.status_update)
        self.update_timer.start(1000)

    def saveSettings(self, indent):
        saveString = []
        idt = indent + "  "
        saveString.append('%s<inputmatrix>\n' % indent)
        saveString.extend(self.inputmatrix.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_inputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</inputmatrix>\n' % indent)

        saveString.append('%s<playbackmatrix>\n' % indent)
        saveString.extend(self.inputmatrix.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_inputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</playbackmatrix>\n' % indent)

        saveString.append('%s<outputmatrix>\n' % indent)
        saveString.extend(self.inputmatrix.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_inputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</outputmatrix>\n' % indent)
        return saveString

    def readSettings(self, readString):
        try:
            idxb = readString.index('<inputmatrix>')
            idxe = readString.index('</inputmatrix>')
        except Exception:
            log.debug("No Input matrix settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb + 1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug(
                        'Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >= 0:
                    if stringMixer[idx + 1].find("Columns_are_inputs") == -1:
                        log.debug(
                            'Transposing the matrix coefficient; you are importing, are not you ?'
                        )
                        transpose_coeff = True
                if self.inputmatrix.readSettings(stringMixer, transpose_coeff):
                    log.debug("Input matrix settings modified")
                del stringMixer

        try:
            idxb = readString.index('<playbackmatrix>')
            idxe = readString.index('</playbackmatrix>')
        except Exception:
            log.debug("No Plaback matrix settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb + 1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug(
                        'Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >= 0:
                    if stringMixer[idx + 1].find("Columns_are_inputs") == -1:
                        log.debug(
                            'Transposing the matrix coefficient; you are importing, are not you ?'
                        )
                        transpose_coeff = True
                if self.playbackmatrix.readSettings(stringMixer,
                                                    transpose_coeff):
                    log.debug("Plaback matrix settings modified")
                del stringMixer

        try:
            idxb = readString.index('<outputmatrix>')
            idxe = readString.index('</outputmatrix>')
        except Exception:
            log.debug("No Output matrix settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb + 1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug(
                        'Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >= 0:
                    if stringMixer[idx + 1].find("Columns_are_inputs") == -1:
                        log.debug(
                            'Transposing the matrix coefficient; you are importing, are not you ?'
                        )
                        transpose_coeff = True
                if self.outputmatrix.readSettings(stringMixer,
                                                  transpose_coeff):
                    log.debug("Output matrix settings modified")
                del stringMixer
Пример #7
0
class Generic_Dice_EAP(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.layout = QGridLayout(self)
        self.setLayout(self.layout)
        self.tabs = QTabWidget(self)
        self.tabs.setTabPosition(QTabWidget.West)
        self.layout.addWidget(self.tabs)

    def buildMixer(self):
        #print( self.hw )
        #print( self.hw.getText("/Generic/Nickname") )
        self.mixer = MatrixMixer(self.hw.servername,
                                 self.hw.basepath + "/EAP/MatrixMixer", self,
                                 "Columns_are_outputs", -1, None, None, False,
                                 QTabWidget.North, QTabWidget.Rounded)
        self.tabs.addTab(self.mixer, "Mixer")

        self.router_scrollarea = self.buildRouter(
            self.hw.servername, self.hw.basepath + "/EAP/Router")
        self.tabs.addTab(self.router_scrollarea, "Crossbar Router")

    def buildRouter(self, servername, path):
        self.router = CrossbarRouter(servername, path, self)
        self.router.MixerRoutingChanged.connect(self.mixer.updateRouting)
        scrollarea = QScrollArea(self.tabs)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.router)
        return scrollarea

    def onSamplerateChange(self):
        # Router configuration is samplerate dependent for DICE EAP devices
        # Destroy and redraw the crossbar router view when called
        n = self.tabs.indexOf(self.router_scrollarea)
        self.tabs.removeTab(n)
        self.router.destroy()
        self.router_scrollarea.destroy()

        self.router_scrollarea = self.buildRouter(
            self.hw.servername, self.hw.basepath + "/EAP/Router")
        self.tabs.insertTab(n, self.router_scrollarea, "Crossbar Router")
        self.tabs.setCurrentWidget(self.router_scrollarea)

        self.mixer.updateRouting()

    def saveSettings(self, indent):
        saveString = []
        idt = indent + "  "
        saveString.append('%s<mixer>\n' % indent)
        saveString.extend(self.mixer.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_outputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</mixer>\n' % indent)
        saveString.append('%s<router>\n' % indent)
        saveString.extend(self.router.saveSettings(idt))
        saveString.append('%s</router>\n' % indent)
        return saveString

    def readSettings(self, readString):
        try:
            idxb = readString.index('<mixer>')
            idxe = readString.index('</mixer>')
        except Exception:
            log.debug("No mixer settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb + 1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug(
                        'Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >= 0:
                    if stringMixer[idx + 1].find("Columns_are_outputs") == -1:
                        log.debug(
                            'Transposing the matrix coefficient; you are importing, are not you ?'
                        )
                        transpose_coeff = True
                if self.mixer.readSettings(stringMixer, transpose_coeff):
                    log.debug("Mixer settings modified")
                del stringMixer
        try:
            idxb = readString.index('<router>')
            idxe = readString.index('</router>')
        except Exception:
            log.debug("No router settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringRouter = []
                for s in readString[idxb + 1:idxe]:
                    stringRouter.append(s)
                if self.router.readSettings(stringRouter):
                    log.debug("Router settings modified")
                del stringRouter
Пример #8
0
class Generic_Dice_EAP(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.layout = QGridLayout(self)
        self.setLayout(self.layout)
        self.tabs = QTabWidget(self)
        self.tabs.setTabPosition(QTabWidget.West)
        self.layout.addWidget(self.tabs)

    def buildMixer(self):
        #print( self.hw )
        #print( self.hw.getText("/Generic/Nickname") )
        self.mixer = MatrixMixer(self.hw.servername, self.hw.basepath+"/EAP/MatrixMixer", self, "Columns_are_outputs", -1, None, None, False, QTabWidget.North, QTabWidget.Rounded)
        self.tabs.addTab(self.mixer, "Mixer")

        self.router_scrollarea = self.buildRouter(self.hw.servername, self.hw.basepath+"/EAP/Router")
        self.tabs.addTab(self.router_scrollarea, "Crossbar Router")

    def buildRouter(self, servername, path):
        self.router = CrossbarRouter(servername, path, self)
        self.router.MixerRoutingChanged.connect(self.mixer.updateRouting)
        scrollarea = QScrollArea(self.tabs)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.router)
        return scrollarea

    def onSamplerateChange(self):
        # Router configuration is samplerate dependent for DICE EAP devices
        # Destroy and redraw the crossbar router view when called
        n = self.tabs.indexOf(self.router_scrollarea)
        self.tabs.removeTab(n)
        self.router.destroy()
        self.router_scrollarea.destroy()

        self.router_scrollarea = self.buildRouter(self.hw.servername, self.hw.basepath+"/EAP/Router")
        self.tabs.insertTab(n, self.router_scrollarea, "Crossbar Router")
        self.tabs.setCurrentWidget(self.router_scrollarea)

        self.mixer.updateRouting()

    def saveSettings(self, indent):
        saveString = []
        idt = indent + "  "
        saveString.append('%s<mixer>\n' % indent)
        saveString.extend(self.mixer.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_outputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</mixer>\n' % indent)
        saveString.append('%s<router>\n' % indent)
        saveString.extend(self.router.saveSettings(idt))
        saveString.append('%s</router>\n' % indent)
        return saveString

    def readSettings(self, readString):
        try:
            idxb = readString.index('<mixer>')
            idxe = readString.index('</mixer>')
        except Exception:
            log.debug("No mixer settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb+1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug('Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >=0:
                    if stringMixer[idx+1].find("Columns_are_outputs") == -1:
                        log.debug('Transposing the matrix coefficient; you are importing, are not you ?')
                        transpose_coeff = True
                if self.mixer.readSettings(stringMixer, transpose_coeff):
                    log.debug("Mixer settings modified")
                del stringMixer
        try:
            idxb = readString.index('<router>')
            idxe = readString.index('</router>')
        except Exception:
            log.debug("No router settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringRouter = []
                for s in readString[idxb+1:idxe]:
                    stringRouter.append(s)
                if self.router.readSettings(stringRouter):
                    log.debug("Router settings modified")
                del stringRouter
Пример #9
0
class Rme(QWidget):
    def __init__(self,parent = None):
        QWidget.__init__(self,parent)
        uicLoad("ffado/mixer/rme", self)

        self.init()

    def init(self):

        self.PhantomSwitches={
            self.phantom_0: ['/Control/Phantom', 0],
            self.phantom_1: ['/Control/Phantom', 1],
            self.phantom_2: ['/Control/Phantom', 2],
            self.phantom_3: ['/Control/Phantom', 3],
        }

        self.Switches={
            self.ff400_chan3_opt_instr: ['/Control/Chan3_opt_instr'],
            self.ff400_chan3_opt_pad:   ['/Control/Chan3_opt_pad'],
            self.ff400_chan4_opt_instr: ['/Control/Chan4_opt_instr'],
            self.ff400_chan4_opt_pad:   ['/Control/Chan4_opt_pad'],

            self.spdif_output_optical:  ['/Control/SPDIF_output_optical', 0],
            self.spdif_output_emphasis: ['/Control/SPDIF_output_emphasis', 0],
            self.spdif_output_pro:      ['/Control/SPDIF_output_pro', 0],
            self.spdif_output_nonaudio: ['/Control/SPDIF_output_nonaudio', 0],
        }

        self.Radiobuttons={
            self.level_in_lo_gain: ['/Control/Input_level', 0],
            self.level_in_p4dBu:   ['/Control/Input_level', 2],
            self.level_in_m10dBV:  ['/Control/Input_level', 1],

            self.level_out_hi_gain: ['/Control/Output_level', 2],
            self.level_out_p4dBu:   ['/Control/Output_level', 1],
            self.level_out_m10dBV:  ['/Control/Output_level', 0],

            self.spdif_input_coax:    ['/Control/SPDIF_input_mode', 0],
            self.spdif_input_optical: ['/Control/SPDIF_input_mode', 1],

            self.phones_hi_gain: ['/Control/Phones_level', 0],
            self.phones_p4dBu:   ['/Control/Phones_level', 1],
            self.phones_m10dBV:  ['/Control/Phones_level', 2],

            self.clock_mode_autosync: ['/Control/Clock_mode', 1],
            self.clock_mode_master: ['/Control/Clock_mode', 0],

            self.sync_ref_wordclk: ['/Control/Sync_ref', 0],
            self.sync_ref_adat1: ['/Control/Sync_ref', 1],
            self.sync_ref_adat2: ['/Control/Sync_ref', 2],
            self.sync_ref_spdif: ['/Control/Sync_ref', 3],
            self.sync_ref_tco: ['/Control/Sync_ref', 4],
        }

        self.Checkboxes={
            self.ch1_instr_fuzz: ['/Control/Chan1_instr_opts', 0x04],
            self.ch1_instr_limiter: ['/Control/Chan1_instr_opts', 0x08],
            self.ch1_instr_filter: ['/Control/Chan1_instr_opts', 0x02],
        }

        self.Gains={
            self.gain_mic1: ['/Control/Gains', 0],
            self.gain_mic2: ['/Control/Gains', 1],
            self.gain_input3: ['/Control/Gains', 2],
            self.gain_input4: ['/Control/Gains', 3],
        }

        self.Combos={
            self.ff800_ch1_src: ['/Control/Chan1_source'],
            self.ff800_ch7_src: ['/Control/Chan7_source'],
            self.ff800_ch8_src: ['/Control/Chan8_source'],
        }

        self.CommandButtons={
            self.control_load: ['/Control/Flash_control', 0],
            self.control_save: ['/Control/Flash_control', 1],
            self.mixer_load:   ['/Control/Flash_control', 2],
            self.mixer_save:   ['/Control/Flash_control', 3],
            self.mixer_preset_ffado_default: ['/Control/Mixer_preset', 0],
        }

        # Other mixer variables
        self.is_streaming = 0
        self.sample_rate = 0
        self.model = 0
        self.tco_present = 0

    # Public slot: update phantom power hardware switches
    def updatePhantomSwitch(self, a0):
        sender = self.sender()
        # Value is the phantom switch value, with a corresponding enable
        # bit in the high 16 bit word
        val = (a0 << self.PhantomSwitches[sender][1]) | (0x00010000 << self.PhantomSwitches[sender][1])
        log.debug("phantom switch %d set to %d" % (self.PhantomSwitches[sender][1], a0))
        self.hw.setDiscrete(self.PhantomSwitches[sender][0], val)

    # Public slot: update generic switches
    def updateSwitch(self, a0):
        sender = self.sender()
        log.debug("switch %s set to %d" % (self.Switches[sender][0], a0))
        self.hw.setDiscrete(self.Switches[sender][0], a0)

    # Public slot: update generic radiobuttons
    def updateRadiobutton(self, a0):
        sender = self.sender()
        if (a0 != 0):
            # Only change the control state on a button being "checked"
            log.debug("radiobutton group %s set to %d" % (self.Radiobuttons[sender][0], self.Radiobuttons[sender][1]))
            self.hw.setDiscrete(self.Radiobuttons[sender][0], self.Radiobuttons[sender][1])

    def updateCheckboxes(self, a0):
        sender = self.sender()
        val = self.hw.getDiscrete(self.Checkboxes[sender][0]);
        if (a0 != 0):
            val = val | self.Checkboxes[sender][1]
        else:
            val = val & ~self.Checkboxes[sender][1]
        log.debug("checkbox group %s set to %d" % (self.Checkboxes[sender][0], val));
        self.hw.setDiscrete(self.Checkboxes[sender][0], val)

    # Public slot: update gains
    def updateGain(self, a0):
        sender = self.sender()
        log.debug("gain %s[%d] set to %d" % (self.Gains[sender][0], self.Gains[sender][1], a0))
        self.hw.setMatrixMixerValue(self.Gains[sender][0], 0, self.Gains[sender][1], a0)

    def updateBandwidthLimit(self, a0):
        # Account for the "No ADAT-2" item which will not be present on
        # a FF400.
        if (self.model==RME_MODEL_FF400 and a0>0):
            a0 = a0 + 1
        # log.debug("limit update: %d" % (a0));
        self.hw.setDiscrete('/Control/Bandwidth_limit', a0);

    # Public slot: send command
    def sendCommand(self, a0):
        sender = self.sender()
        log.debug("command %d sent to %s" % (self.CommandButtons[sender][1], self.CommandButtons[sender][0]))
        self.hw.setDiscrete(self.CommandButtons[sender][0], self.CommandButtons[sender][1])

        # If mixer values have been reloaded, refresh the mixer GUI.  This
        # will also commit the new values to the hardware via the "changed"
        # signal handlers of the mixer elements.
        if (self.CommandButtons[sender][1] == 2):
            self.inputmatrix.refreshValues()
            self.outputmatrix.refreshValues()
            self.playbackmatrix.refreshValues()

        # If settings have been reloaded from flash, refresh the GUI.  The
        # settings will be made active in the hardware via the "changed"
        # signal handlers of the respective GUI control widgets.
        if (self.CommandButtons[sender][1] == 0):
            self.getValuesFromFF()

    def updateCombo(self, a0):
        sender = self.sender()
        log.debug("combo %s set to %d" % (self.Combos[sender][0], a0))
        self.hw.setDiscrete(self.Combos[sender][0], a0)

        # Enable the limiter control only when the front source is active
        if (sender == self.ff800_ch1_src):
            self.ch1_instr_limiter.setEnabled(a0==0)

    def updateStreamingState(self):
        ss = self.streamingstatus.selected()
        ss_txt = self.streamingstatus.getEnumLabel(ss)
        if ss_txt != 'Idle':
            self.is_streaming = True
        else:
            self.is_streaming = False
        if (self.last_streaming_state != self.is_streaming):
            self.bandwidth_limit.setEnabled(not(self.is_streaming));
            self.control_load.setEnabled(not(self.is_streaming));
        self.last_streaming_state = self.is_streaming

    def status_update(self):
        # log.debug("timer event")
        self.updateStreamingState()
        clk_mode = ['Master', 'Slave']
        src_str = ['None', 'ADAT 1', 'ADAT 2', 'SPDIF', 'Wordclock', 'TCO']
        sync_stat = ['No lock', 'Locked', 'Synced']
        sysclock_mode = self.hw.getDiscrete('/Control/sysclock_mode')
        sysclock_freq = self.hw.getDiscrete('/Control/sysclock_freq')
        autosync_freq = self.hw.getDiscrete('/Control/autosync_freq')
        autosync_src = self.hw.getDiscrete('/Control/autosync_src')
        sync_status = self.hw.getDiscrete('/Control/sync_status')
        spdif_freq = self.hw.getDiscrete('/Control/spdif_freq')
        self.sysclock_freq.setText("%d Hz" % (sysclock_freq))
        self.sysclock_mode.setText(clk_mode[sysclock_mode])
        self.autosync_freq.setText("%d Hz" % (autosync_freq))
        self.autosync_src.setText(src_str[autosync_src])
        self.sync_check_adat1_status.setText(sync_stat[sync_status & 0x03])
        self.sync_check_adat2_status.setText(sync_stat[(sync_status >> 2) & 0x03])
        self.sync_check_spdif_status.setText(sync_stat[(sync_status >> 4) & 0x03])
        self.sync_check_wclk_status.setText(sync_stat[(sync_status >> 6) & 0x03])
        self.sync_check_tco_status.setText(sync_stat[(sync_status >> 8) & 0x03])
        self.spdif_freq.setText("%d Hz" % (spdif_freq))

    # Hide and disable a control
    def disable_hide(self,widget):
        for w in widget.children():
            if isinstance(w, QWidget):
                w.hide()
                w.setEnabled(False)
        widget.hide()
        widget.setEnabled(False)

    def setupSignals(self):

        # Connect signal handlers for all command buttons
        for ctrl, info in self.CommandButtons.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            QObject.connect(ctrl, SIGNAL('clicked(bool)'), self.sendCommand)

        for ctrl, info in self.Combos.iteritems():
            if (not(ctrl.isEnabled())):
                continue;
            QObject.connect(ctrl, SIGNAL('currentIndexChanged(int)'), self.updateCombo)

        QObject.connect(self.bandwidth_limit, SIGNAL('currentIndexChanged(int)'), self.updateBandwidthLimit)

        # Get current hardware values and connect GUI element signals to 
        # their respective slots
        for ctrl, info in self.PhantomSwitches.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            QObject.connect(ctrl, SIGNAL('toggled(bool)'), self.updatePhantomSwitch)

        for ctrl, info in self.Switches.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            QObject.connect(ctrl, SIGNAL('toggled(bool)'), self.updateSwitch)

        for ctrl, info in self.Radiobuttons.iteritems():
            if (not(ctrl.isEnabled())):
                continue;
            QObject.connect(ctrl, SIGNAL('toggled(bool)'), self.updateRadiobutton)

        for ctrl, info in self.Checkboxes.iteritems():
            if (not(ctrl.isEnabled())):
                continue;
            QObject.connect(ctrl, SIGNAL('toggled(bool)'), self.updateCheckboxes)

        for ctrl, info in self.Gains.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            QObject.connect(ctrl, SIGNAL('valueChanged(int)'), self.updateGain)

    # Obtain control values from the Fireface and make the GUI reflect these
    def getValuesFromFF(self):
        for ctrl, info in self.Combos.iteritems():
            if (not(ctrl.isEnabled())):
                continue;
            val = self.hw.getDiscrete(info[0])
            log.debug("combo %s is %d" % (info[0], val));
            ctrl.setCurrentIndex(val);

        # Set the bandwidth limit control to reflect the current device
        # setting, allowing for the additional "No ADAT-2" item which is
        # present on the FF800.
        val = self.hw.getDiscrete('/Control/Bandwidth_limit')
        if (self.model==RME_MODEL_FF400 and val>1):
            val = val - 1
        self.bandwidth_limit.setCurrentIndex(val);

        # Get current hardware values
        for ctrl, info in self.PhantomSwitches.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            val = (self.hw.getDiscrete(info[0]) >> info[1]) & 0x01
            log.debug("phantom switch %d is %d" % (info[1], val))
            if val:
                ctrl.setChecked(True)
            else:
                ctrl.setChecked(False)

        for ctrl, info in self.Switches.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            val = self.hw.getDiscrete(info[0])
            log.debug("switch %s is %d" % (info[0], val))
            if val:
                ctrl.setChecked(True)
            else:
                ctrl.setChecked(False)

        for ctrl, info in self.Radiobuttons.iteritems():
            if (not(ctrl.isEnabled())):
                continue;
            # This is a touch wasteful since it means we retrieve the control
            # value once per radio button rather than once per radio button
            # group.  In time we might introduce radiobutton groupings in the
            # self.* datastructures to avoid this, but for the moment this is
            # easy and it works.
            val = self.hw.getDiscrete(info[0])
            if (val == info[1]):
                val = 1
            else:
                val = 0
            ctrl.setChecked(val)
            log.debug("Radiobutton %s[%d] is %d" % (info[0], info[1], val))

        # Make sure the Limiter control can receive a value
        if (self.ff800_ch1_src.isEnabled()):
            self.ch1_instr_limiter.setEnabled(1)

        for ctrl, info in self.Checkboxes.iteritems():
            if (not(ctrl.isEnabled())):
                continue;
            # This is a touch wasteful since it means we retrieve the control
            # value once per checkbox button rather than once per checkbox
            # group.  In time we might introduce checkbox groupings in the
            # self.* datastructures to avoid this, but for the moment this is
            # easy and it works.
            val = self.hw.getDiscrete(info[0])
            if (val & info[1]):
                val = 1
            else:
                val = 0
            ctrl.setChecked(val)
            log.debug("Checkbox %s[%d] is %d" % (info[0], info[1], val))

        # The limiter (a checkbox) can only be controlled if the front
        # source is selected for channel 1.
        ch1_src = self.ff800_ch1_src.currentIndex()
        if (self.ff800_ch1_src.isEnabled()):
            self.ch1_instr_limiter.setEnabled(ch1_src==0)

        for ctrl, info in self.Gains.iteritems():
            if (not(ctrl.isEnabled())):
                continue
            val = self.hw.getMatrixMixerValue(info[0], 0, info[1])
            log.debug("gain %s[%d] is %d" % (info[0], info[1], val))
            ctrl.setValue(val);



    def initValues(self):

        # print self.hw.servername
        # print self.hw.basepath
        self.inputmatrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/Mixer/InputFaders", self, "Columns_are_inputs", 0x8000, self.hw.basepath+"/Mixer/InputMutes", self.hw.basepath+"/Mixer/InputInverts", True)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.inputmatrix)
        self.mixer.setLayout(layout)

        self.playbackmatrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/Mixer/PlaybackFaders", self, "Columns_are_inputs", 0x8000, self.hw.basepath+"/Mixer/PlaybackMutes", self.hw.basepath+"/Mixer/PlaybackInverts", True)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.playbackmatrix)
        self.playbackmixer.setLayout(layout)

        self.outputmatrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/Mixer/OutputFaders", self, "Columns_are_inputs", 0x8000, self.hw.basepath+"/Mixer/OutputMutes", None, True)
        layout = QtGui.QVBoxLayout()

        # This is a bit of a hack, but it works to ensure this single-row
        # matrix mixer doesn't fill the entire screen but also doesn't end
        # up with a pointless scrollbar.  The matrix mixer's minimum height
        # is 0 according to minimumHeight(), which is probably the
        # fundamental issue here; however, I've already wasted too much time
        # trying to get this to work so if the hack is effective we'll run
        # with it.
        self.outputmatrix.setMinimumHeight(150)
        layout.addWidget(self.outputmatrix, 0, Qt.AlignTop)
        self.outputmixer.setLayout(layout)

        self.is_streaming = False
        self.last_streaming_state = False

        # Disable the "load settings" button if streaming is active.  Its
        # enable state will be kept up to date by updateStreamingState().
        self.control_load.setEnabled(not(self.is_streaming))

        # Also disable other controls which are not yet implemented.
        self.mixer_preset_ffado_default.setEnabled(False)

        # Retrieve other device settings as needed and customise the UI
        # based on these options.
        self.model = self.hw.getDiscrete('/Control/Model')
        log.debug("device model identifier: %d" % (self.model))
        self.tco_present = self.hw.getDiscrete('/Control/TCO_present')
        log.debug("device has TCO: %d" % (self.tco_present))
        #self.sample_rate = self.hw.getDiscrete('/Mixer/Info/SampleRate')
        #log.debug("device sample rate: %d" % (self.sample_rate))

        # The Fireface-400 only has 2 phantom-capable channels
        if (self.model == RME_MODEL_FF400):
            self.disable_hide(self.phantom_2)
            self.disable_hide(self.phantom_3)
        else:
            self.phantom_0.setText("Mic 7")
            self.phantom_1.setText("Mic 8")
            self.phantom_2.setText("Mic 9")
            self.phantom_3.setText("Mic 10")

        # Instrument options, input jack selection controls and an ADAT2
        # input are applicable only to the FF800
        if (self.model != RME_MODEL_FF800):
            self.instrument_options_group.setEnabled(False)
            self.input_plug_select_group.setEnabled(False)
            self.sync_ref_adat2.setEnabled(False)
            self.sync_check_adat2_label.setEnabled(False)
            self.sync_check_adat2_status.setEnabled(False)

        if (not(self.tco_present)):
            self.sync_check_tco_label.setEnabled(False)
            self.sync_check_tco_status.setEnabled(False)
            self.sync_ref_tco.setEnabled(False)

        # Only the FF400 has specific channel 3/4 options, input gain
        # controls and switchable phones level
        if (self.model != RME_MODEL_FF400):
            # Hide the upper-level frame (and everything in it) to ensure it 
            # requests no vertical space when its contents aren't needed.
            self.disable_hide(self.igains_chan34_opts_frame)
            self.phones_level_group.setEnabled(False)

        # Add the "No ADAT-2" item to the bandwidth limit control if the
        # device is not a FF400.
        if (self.model != RME_MODEL_FF400):
            self.bandwidth_limit.insertItem(1, "No ADAT-2")

        self.getValuesFromFF()
        self.setupSignals()

        # Ensure the limiter checkbox has a signal handler associated with
        # it.  If getValuesFromFF() disabled it because the front input was
        # not selected, setupSignals() would not have configured a handler.
        if (not(self.ch1_instr_limiter.isEnabled())):
            QObject.connect(self.ch1_instr_limiter, SIGNAL('toggled(bool)'), self.updateCheckboxes)

        self.updateStreamingState()
        #log.debug("device streaming flag: %d" % (self.is_streaming))

        self.update_timer = QTimer(self)
        QObject.connect(self.update_timer, SIGNAL('timeout()'), self.status_update)
        self.update_timer.start(1000)

    def saveSettings(self, indent):
        saveString = []
        idt = indent + "  "
        saveString.append('%s<inputmatrix>\n' % indent)
        saveString.extend(self.inputmatrix.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_inputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</inputmatrix>\n' % indent)

        saveString.append('%s<playbackmatrix>\n' % indent)
        saveString.extend(self.inputmatrix.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_inputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</playbackmatrix>\n' % indent)

        saveString.append('%s<outputmatrix>\n' % indent)
        saveString.extend(self.inputmatrix.saveSettings(idt))
        # Do not forget to mention the adopted rule for matrix columns mixer
        #  This might be useful for future import function
        saveString.append("%s  <col_rule>\n" % indent)
        saveString.append("%s    Columns_are_inputs\n" % indent)
        saveString.append("%s  </col_rule>\n" % indent)
        saveString.append('%s</outputmatrix>\n' % indent)
        return saveString

    def readSettings(self, readString):
        try:
            idxb = readString.index('<inputmatrix>')
            idxe = readString.index('</inputmatrix>')
        except Exception:
            log.debug("No Input matrix settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb+1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug('Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >=0:
                    if stringMixer[idx+1].find("Columns_are_inputs") == -1:
                        log.debug('Transposing the matrix coefficient; you are importing, are not you ?')
                        transpose_coeff = True
                if self.inputmatrix.readSettings(stringMixer, transpose_coeff):
                    log.debug("Input matrix settings modified")
                del stringMixer

        try:
            idxb = readString.index('<playbackmatrix>')
            idxe = readString.index('</playbackmatrix>')
        except Exception:
            log.debug("No Plaback matrix settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb+1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug('Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >=0:
                    if stringMixer[idx+1].find("Columns_are_inputs") == -1:
                        log.debug('Transposing the matrix coefficient; you are importing, are not you ?')
                        transpose_coeff = True
                if self.playbackmatrix.readSettings(stringMixer, transpose_coeff):
                    log.debug("Plaback matrix settings modified")
                del stringMixer

        try:
            idxb = readString.index('<outputmatrix>')
            idxe = readString.index('</outputmatrix>')
        except Exception:
            log.debug("No Output matrix settings found")
            idxb = -1
            idxe = -1
        if idxb >= 0:
            if idxe > idxb + 1:
                stringMixer = []
                for s in readString[idxb+1:idxe]:
                    stringMixer.append(s)
                # When trying to import from a different device, the rule for column interpretation is
                # not necessarily the same
                try:
                    idx = stringMixer.index('<col_rule>')
                except Exception:
                    log.debug('Do not know how to handle column versus input/output')
                    idx = -1
                transpose_coeff = False
                if idx >=0:
                    if stringMixer[idx+1].find("Columns_are_inputs") == -1:
                        log.debug('Transposing the matrix coefficient; you are importing, are not you ?')
                        transpose_coeff = True
                if self.outputmatrix.readSettings(stringMixer, transpose_coeff):
                    log.debug("Output matrix settings modified")
                del stringMixer
Пример #10
0
    def initValues(self):

        # print self.hw.servername
        # print self.hw.basepath
        self.inputmatrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/Mixer/InputFaders", self, "Columns_are_inputs", 0x8000, self.hw.basepath+"/Mixer/InputMutes", self.hw.basepath+"/Mixer/InputInverts", True)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.inputmatrix)
        self.mixer.setLayout(layout)

        self.playbackmatrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/Mixer/PlaybackFaders", self, "Columns_are_inputs", 0x8000, self.hw.basepath+"/Mixer/PlaybackMutes", self.hw.basepath+"/Mixer/PlaybackInverts", True)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.playbackmatrix)
        self.playbackmixer.setLayout(layout)

        self.outputmatrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/Mixer/OutputFaders", self, "Columns_are_inputs", 0x8000, self.hw.basepath+"/Mixer/OutputMutes", None, True)
        layout = QtGui.QVBoxLayout()

        # This is a bit of a hack, but it works to ensure this single-row
        # matrix mixer doesn't fill the entire screen but also doesn't end
        # up with a pointless scrollbar.  The matrix mixer's minimum height
        # is 0 according to minimumHeight(), which is probably the
        # fundamental issue here; however, I've already wasted too much time
        # trying to get this to work so if the hack is effective we'll run
        # with it.
        self.outputmatrix.setMinimumHeight(150)
        layout.addWidget(self.outputmatrix, 0, Qt.AlignTop)
        self.outputmixer.setLayout(layout)

        self.is_streaming = False
        self.last_streaming_state = False

        # Disable the "load settings" button if streaming is active.  Its
        # enable state will be kept up to date by updateStreamingState().
        self.control_load.setEnabled(not(self.is_streaming))

        # Also disable other controls which are not yet implemented.
        self.mixer_preset_ffado_default.setEnabled(False)

        # Retrieve other device settings as needed and customise the UI
        # based on these options.
        self.model = self.hw.getDiscrete('/Control/Model')
        log.debug("device model identifier: %d" % (self.model))
        self.tco_present = self.hw.getDiscrete('/Control/TCO_present')
        log.debug("device has TCO: %d" % (self.tco_present))
        #self.sample_rate = self.hw.getDiscrete('/Mixer/Info/SampleRate')
        #log.debug("device sample rate: %d" % (self.sample_rate))

        # The Fireface-400 only has 2 phantom-capable channels
        if (self.model == RME_MODEL_FF400):
            self.disable_hide(self.phantom_2)
            self.disable_hide(self.phantom_3)
        else:
            self.phantom_0.setText("Mic 7")
            self.phantom_1.setText("Mic 8")
            self.phantom_2.setText("Mic 9")
            self.phantom_3.setText("Mic 10")

        # Instrument options, input jack selection controls and an ADAT2
        # input are applicable only to the FF800
        if (self.model != RME_MODEL_FF800):
            self.instrument_options_group.setEnabled(False)
            self.input_plug_select_group.setEnabled(False)
            self.sync_ref_adat2.setEnabled(False)
            self.sync_check_adat2_label.setEnabled(False)
            self.sync_check_adat2_status.setEnabled(False)

        if (not(self.tco_present)):
            self.sync_check_tco_label.setEnabled(False)
            self.sync_check_tco_status.setEnabled(False)
            self.sync_ref_tco.setEnabled(False)

        # Only the FF400 has specific channel 3/4 options, input gain
        # controls and switchable phones level
        if (self.model != RME_MODEL_FF400):
            # Hide the upper-level frame (and everything in it) to ensure it 
            # requests no vertical space when its contents aren't needed.
            self.disable_hide(self.igains_chan34_opts_frame)
            self.phones_level_group.setEnabled(False)

        # Add the "No ADAT-2" item to the bandwidth limit control if the
        # device is not a FF400.
        if (self.model != RME_MODEL_FF400):
            self.bandwidth_limit.insertItem(1, "No ADAT-2")

        self.getValuesFromFF()
        self.setupSignals()

        # Ensure the limiter checkbox has a signal handler associated with
        # it.  If getValuesFromFF() disabled it because the front input was
        # not selected, setupSignals() would not have configured a handler.
        if (not(self.ch1_instr_limiter.isEnabled())):
            QObject.connect(self.ch1_instr_limiter, SIGNAL('toggled(bool)'), self.updateCheckboxes)

        self.updateStreamingState()
        #log.debug("device streaming flag: %d" % (self.is_streaming))

        self.update_timer = QTimer(self)
        QObject.connect(self.update_timer, SIGNAL('timeout()'), self.status_update)
        self.update_timer.start(1000)
Пример #11
0
    def initValues(self):

        # print self.hw.servername
        # print self.hw.basepath
        self.inputmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/InputFaders", self,
            0x8000, self.hw.basepath + "/Mixer/InputMutes",
            self.hw.basepath + "/Mixer/InputInverts", True)
        layout = QtGui.QVBoxLayout()
        scrollarea = QtGui.QScrollArea()
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.inputmatrix)
        layout.addWidget(scrollarea)
        self.mixer.setLayout(layout)

        self.playbackmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/PlaybackFaders",
            self, 0x8000, self.hw.basepath + "/Mixer/PlaybackMutes",
            self.hw.basepath + "/Mixer/PlaybackInverts", True)
        layout = QtGui.QVBoxLayout()
        scrollarea = QtGui.QScrollArea()
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(self.playbackmatrix)
        layout.addWidget(scrollarea)
        self.playbackmixer.setLayout(layout)

        self.outputmatrix = MatrixMixer(
            self.hw.servername, self.hw.basepath + "/Mixer/OutputFaders", self,
            0x8000, self.hw.basepath + "/Mixer/OutputMutes", None, True)
        layout = QtGui.QVBoxLayout()
        scrollarea = QtGui.QScrollArea()
        scrollarea.setWidget(self.outputmatrix)
        scrollarea.setWidgetResizable(True)

        # This is a bit of a hack, but it works to ensure this single-row
        # matrix mixer doesn't fill the entire screen but also doesn't end
        # up with a pointless scrollbar.  The matrix mixer's minimum height
        # is 0 according to minimumHeight(), which is probably the
        # fundamental issue here; however, I've already wasted too much time
        # trying to get this to work so if the hack is effective we'll run
        # with it.
        scrollarea.setMinimumHeight(150)
        layout.addWidget(scrollarea, 0, Qt.AlignTop)
        self.outputmixer.setLayout(layout)

        self.is_streaming = False
        self.last_streaming_state = False

        # Retrieve other device settings as needed and customise the UI
        # based on these options.
        self.model = self.hw.getDiscrete('/Control/Model')
        log.debug("device model identifier: %d" % (self.model))
        self.tco_present = self.hw.getDiscrete('/Control/TCO_present')
        log.debug("device has TCO: %d" % (self.tco_present))
        #self.sample_rate = self.hw.getDiscrete('/Mixer/Info/SampleRate')
        #log.debug("device sample rate: %d" % (self.sample_rate))

        # The Fireface-400 only has 2 phantom-capable channels
        if (self.model == RME_MODEL_FF400):
            self.disable_hide(self.phantom_2)
            self.disable_hide(self.phantom_3)
        else:
            self.phantom_0.setText("Mic 7")
            self.phantom_1.setText("Mic 8")
            self.phantom_2.setText("Mic 9")
            self.phantom_3.setText("Mic 10")

        # Instrument options, input jack selection controls and an ADAT2
        # input are applicable only to the FF800
        if (self.model != RME_MODEL_FF800):
            self.instrument_options_group.setEnabled(False)
            self.input_plug_select_group.setEnabled(False)
            self.sync_ref_adat2.setEnabled(False)
            self.sync_check_adat2_label.setEnabled(False)
            self.sync_check_adat2_status.setEnabled(False)

        for ctrl, info in self.Combos.iteritems():
            if (not (ctrl.isEnabled())):
                continue
            val = self.hw.getDiscrete(info[0])
            log.debug("combo %s is %d" % (info[0], val))
            ctrl.setCurrentIndex(val)
            QObject.connect(ctrl, SIGNAL('currentIndexChanged(int)'),
                            self.updateCombo)

        if (not (self.tco_present)):
            self.sync_check_tco_label.setEnabled(False)
            self.sync_check_tco_status.setEnabled(False)
            self.sync_ref_tco.setEnabled(False)

        # Only the FF400 has specific channel 3/4 options, input gain
        # controls and switchable phones level
        if (self.model != RME_MODEL_FF400):
            self.disable_hide(self.input_gains_group)
            self.disable_hide(self.channel_3_4_options_group)
            self.phones_level_group.setEnabled(False)

        # Add the "No ADAT-2" item to the bandwidth limit control if the
        # device is not a FF400.  Set the control to reflect the current
        # device setting and connect an update signal.
        if (self.model != RME_MODEL_FF400):
            self.bandwidth_limit.insertItem(1, "No ADAT-2")
        val = self.hw.getDiscrete('/Control/Bandwidth_limit')
        if (self.model == RME_MODEL_FF400 and val > 1):
            val = val - 1
        self.bandwidth_limit.setCurrentIndex(val)
        QObject.connect(self.bandwidth_limit,
                        SIGNAL('currentIndexChanged(int)'),
                        self.updateBandwidthLimit)

        # Get current hardware values and connect GUI element signals to
        # their respective slots
        for ctrl, info in self.PhantomSwitches.iteritems():
            if (not (ctrl.isEnabled())):
                continue
            val = (self.hw.getDiscrete(info[0]) >> info[1]) & 0x01
            log.debug("phantom switch %d is %d" % (info[1], val))
            if val:
                ctrl.setChecked(True)
            else:
                ctrl.setChecked(False)
            QObject.connect(ctrl, SIGNAL('toggled(bool)'),
                            self.updatePhantomSwitch)

        for ctrl, info in self.Switches.iteritems():
            if (not (ctrl.isEnabled())):
                continue
            val = self.hw.getDiscrete(info[0])
            log.debug("switch %s is %d" % (info[0], val))
            if val:
                ctrl.setChecked(True)
            else:
                ctrl.setChecked(False)
            QObject.connect(ctrl, SIGNAL('toggled(bool)'), self.updateSwitch)

        for ctrl, info in self.Radiobuttons.iteritems():
            if (not (ctrl.isEnabled())):
                continue
            # This is a touch wasteful since it means we retrieve the control
            # value once per radio button rather than once per radio button
            # group.  In time we might introduce radiobutton groupings in the
            # self.* datastructures to avoid this, but for the moment this is
            # easy and it works.
            val = self.hw.getDiscrete(info[0])
            if (val == info[1]):
                val = 1
            else:
                val = 0
            ctrl.setChecked(val)
            log.debug("Radiobutton %s[%d] is %d" % (info[0], info[1], val))
            QObject.connect(ctrl, SIGNAL('toggled(bool)'),
                            self.updateRadiobutton)

        for ctrl, info in self.Checkboxes.iteritems():
            if (not (ctrl.isEnabled())):
                continue
            # This is a touch wasteful since it means we retrieve the control
            # value once per checkbox button rather than once per checkbox
            # group.  In time we might introduce checkbox groupings in the
            # self.* datastructures to avoid this, but for the moment this is
            # easy and it works.
            val = self.hw.getDiscrete(info[0])
            if (val & info[1]):
                val = 1
            else:
                val = 0
            ctrl.setChecked(val)
            log.debug("Checkbox %s[%d] is %d" % (info[0], info[1], val))
            QObject.connect(ctrl, SIGNAL('toggled(bool)'),
                            self.updateCheckboxes)

        for ctrl, info in self.Gains.iteritems():
            if (not (ctrl.isEnabled())):
                continue
            val = self.hw.getMatrixMixerValue(info[0], 0, info[1])
            log.debug("gain %s[%d] is %d" % (info[0], info[1], val))
            ctrl.setValue(val)
            QObject.connect(ctrl, SIGNAL('valueChanged(int)'), self.updateGain)

        self.updateStreamingState()
        #log.debug("device streaming flag: %d" % (self.is_streaming))

        self.update_timer = QTimer(self)
        QObject.connect(self.update_timer, SIGNAL('timeout()'),
                        self.status_update)
        self.update_timer.start(1000)