Exemple #1
0
class Main(QtWidgets.QMainWindow):

    debug = debug

    width = 1000
    height = 100
    offset_left = 100
    offset_top = 30
    max_tab_width = 1000
    min_tab_width = 480

    # HANDLES
    idle_screen = False
    idle_toggable = True

    # create signals
    sig_idle_screen = pyqtSignal(object)

    def __init__( self, app, options=None, parent=None):
        QtCore.QObject.__init__(self, parent)
        self.app = app

        if os.name == 'posix':
            self.label_font_size = 18
        else:
            self.label_font_size = 12
        
        # #################
        # INITIATE
        self.control = Control(self, self.debug)

        # #################
        # LAYOUTS
        self.init_layout()

        self.setGeometry(self.offset_left, self.offset_top, self.width, self.height)
        self.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        self.setMinimumSize(self.width, self.height)
        self.setWindowTitle(self.control.name)

        # for thread in self.control.threads:
        #     print thread

        # #################
        self.control.start_capture()

    def init_layout(self):
        # main
        self.main = QtWidgets.QWidget()
        self.setCentralWidget(self.main)
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main.setLayout(self.main_layout)
        self.bottom_layout = QtWidgets.QHBoxLayout()
        self.bottom_info_layout = QtWidgets.QHBoxLayout()
        
        # self.create_menu_bar()

        # optional
        if self.control.cfg['video_input']:
            self.init_video_display()
        if self.control.cfg['audio_input']:
            self.init_audio_in_display()
        if self.control.cfg['audio_output']:
            self.init_audio_out_display()

        # add control: buttons and info
        self.init_control_layout()
        # create keyboard shortcuts
        self.create_actions()

    def init_audio_in_display(self):
        # AUDIO DISPLAY
        self.height += 200
        self.audio_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addLayout(self.audio_layout)

        self.audio_disp = AudioDisplay(self, self.control.devices.audiodev, 'Audio Input', 
            samplerate=self.control.cfg['audio_input_samplerate'])
        self.audio_layout.addWidget(self.audio_disp)

    def init_audio_out_display(self):
        self.height += 200
        self.audioout_disp = AudioDisplay(self, self.control.devices.audiodevout, 'Audio Output', 
            playback=True)
        self.audio_layout.addWidget(self.audioout_disp)
        if self.control.options.audio_playback_list:
            self.control.exp_control.sig_exp_finished.connect(self.enable_start)
        elif self.control.options.audio_playback:
            self.control.devices.audiodevout.sig_playback_finished.connect(self.enable_start)

        self.setGeometry(self.offset_left, self.offset_top, self.width, self.height)
        self.setMinimumSize(self.width, self.height)

    def init_control_layout(self):
        self.main_layout.addLayout(self.bottom_layout)
        self.main_layout.addLayout(self.bottom_info_layout)

        # POPULATE BOTTOM LAYOUT
        self.button_record = QtWidgets.QPushButton('Start Recording')
        self.button_stop = QtWidgets.QPushButton('Stop')
        self.button_tag = QtWidgets.QPushButton('&Comment')
        self.button_idle = QtWidgets.QPushButton('Pause Display')

        self.button_stop.setDisabled(True)
        self.button_tag.setDisabled(True)

        self.button_record.setMinimumHeight(50)
        self.button_stop.setMinimumHeight(50)
        self.button_tag.setMinimumHeight(50)
        self.button_idle.setMinimumHeight(50)

        self.bottom_layout.addWidget(self.button_record)
        self.bottom_layout.addWidget(self.button_stop)
        self.bottom_layout.addWidget(self.button_tag)
        self.bottom_layout.addWidget(self.button_idle)

        self.label_time = QtWidgets.QLabel('', self)
        font = self.label_time.font()
        font.setPointSize(self.label_font_size)
        self.label_time.setFont(font)
        self.label_time.setText(self.control.default_label_text)
        self.control.sig_info_update.connect(self.update_info)

        self.bottom_info_layout.addStretch(0)
        self.bottom_info_layout.addWidget(self.label_time)
        self.bottom_info_layout.addStretch(0)

        # connect buttons
        self.button_record.clicked.connect(self.clicked_start)
        self.button_stop.clicked.connect(self.clicked_stop)
        self.button_tag.clicked.connect(self.clicked_comment)
        self.button_idle.clicked.connect(self.clicked_idle)
        

    def init_video_display(self):
        self.video_layout = QtWidgets.QHBoxLayout()
        self.main_layout.addLayout(self.video_layout)
        self.height += 500

        # POPULATE TOP LAYOUT
        self.videos = QtWidgets.QTabWidget()
        self.videos.setMinimumWidth(self.min_tab_width)
        self.videos.setMaximumWidth(self.max_tab_width)
        self.video_recordings = None
        self.video_tabs = {}
        self.video_layout.addWidget(self.videos)

        if len(self.control.devices.cameras) > 0:
            # create tabs for cameras
            for cam_name, cam in self.control.devices.cameras.items():
                self.video_tabs[cam_name] = VideoTab(self, cam_name)
                self.videos.addTab(self.video_tabs[cam_name], cam_name)

        else:
            self.videos.addTab(QtWidgets.QWidget(), "No camera found")

        # create timer for updating the video canvas
        self.canvastimer = QtCore.QTimer()
        self.canvastimer.timeout.connect(self.update_canvas)
        if len(self.control.devices.cameras):
            self.canvastimer.start(50)  # 20 Hz

    def create_menu_bar(self):
        self.statusBar()
        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu('&File')
        file_menu.addAction(self.exit_action)
        help_menu = menu_bar.addMenu('&Help')

    # ACTIONS
    # Actions can be used to assign keyboard-shortcuts
    # This method is called in the __init__ method to create keyboard shortcuts
    def create_actions(self):
        # Create a start stop action for starts
        self.action_start_stop_delayed = QtWidgets.QAction('Start, stop recording',self)
        self.action_start_stop_delayed.setShortcut(Qt.Key_Space)
        self.action_start_stop_delayed.triggered.connect(self.start_stop)
        self.addAction(self.action_start_stop_delayed)

        # Create a Tag
        self.action_tag = QtWidgets.QAction('Comment recording',self)
        self.action_tag.setShortcut('Ctrl+T')
        self.action_tag.triggered.connect(self.clicked_comment)
        self.addAction(self.action_tag)

        # Change Tabs
        # self.action_change_tab_left = QtWidgets.QAction("Go one tab to the right", self)
        # self.action_change_tab_left.setShortcut(Qt.CTRL + Qt.Key_PageDown)
        # self.connect(self.action_change_tab_left, QtCore.SIGNAL('triggered()'), self.next_tab)
        # self.addAction(self.action_change_tab_left)

        # self.action_change_tab_right = QtWidgets.QAction("Go one tab to the left", self)
        # self.action_change_tab_right.setShortcut(Qt.CTRL + Qt.Key_PageUp)
        # self.connect(self.action_change_tab_right, QtCore.SIGNAL('triggered()'), self.prev_tab)
        # self.addAction(self.action_change_tab_right)

        # Exit
        self.exit_action = QtWidgets.QAction('&Exit', self)
        self.exit_action.setShortcut('Alt+Q')
        self.exit_action.triggered.connect(self.close)
        self.addAction(self.exit_action)

    def start_stop(self):
        """ for action """
        if self.debug > 0:
            print('start_stop called')
        if not self.button_record.isEnabled():
            self.clicked_stop()
        else:
            self.clicked_start()

    def clicked_start(self):
        self.disable_start()
        self.control.triggered_start()

    def clicked_stop(self):
        self.enable_start()
        self.control.triggered_stop()

    def enable_start(self):
        print('enabled start')
        self.button_record.setDisabled(False)
        self.button_stop.setDisabled(True)
        self.button_tag.setDisabled(True)

    def disable_start(self):
        print('disabled start')
        self.button_record.setDisabled(True)
        self.button_tag.setEnabled(True)
        self.button_stop.setDisabled(False)

    def clicked_comment(self):
        timestamp = datetime.now().strftime("%Y-%m-%d  %H:%M:%S")
        dlg =  QtWidgets.QInputDialog(self)
        dlg.setInputMode(QtWidgets.QInputDialog.TextInput)
        dlg.setLabelText('Comment on data:')                        
        dlg.setWindowTitle('Comment')
        dlg.resize(500,200)
        ok = dlg.exec_()  # shows the dialog
        s = u'{} \t {}'.format(timestamp, dlg.textValue())
        if ok:
            self.control.set_timestamp(s)

    def clicked_idle(self):
        if not self.idle_toggable: return
        if self.idle_screen:
            self.idle_screen = False
            self.button_idle.setText('Pause Display')
            self.sig_idle_screen.emit(False)
        else:
            self.idle_screen = True
            self.button_idle.setText('Continue Display')
            self.sig_idle_screen.emit(True)

    def next_tab(self):
        if self.tab.currentIndex() + 1 < self.tab.count():
            self.tab.setCurrentIndex(self.tab.currentIndex() + 1)
        else:
            self.tab.setCurrentIndex(0)

    def prev_tab(self):
        if self.tab.currentIndex() > 0:
            self.tab.setCurrentIndex(self.tab.currentIndex() - 1)
        else:
            self.tab.setCurrentIndex(self.tab.count() - 1)

    def update_info(self, label):
        self.label_time.setText(label)

    def closeEvent(self, event):
        self.control.stop_all_saving()
        QtCore.QThread.msleep(200)
        self.control.stop_all_capture()

        # finish threads
        for thread in self.control.threads:
            thread.quit()
        QtCore.QThread.msleep(200)
        print('See ya ...')
        self.app.quit()

    def update_canvas(self):
        # print('update canvas '+str(QtCore.QThread.currentThread()))
        # check for programmed stop-time
        if self.control.programmed_stop_dt is not None \
           and self.programmed_stop_dt < datetime.now():
            self.stop_all_recordings()
            # wait for recordings to stop
            self.wait(100)
            self.app.exit()

        # grab data from camera and display
        cam_name = str(self.videos.tabText(self.videos.currentIndex()))

        if not self.idle_screen:
            data = self.control.devices.cameras[cam_name].get_dispframe()  # grab current frame
            if data is None:
                return
            frame, dtime, fr = data
            self.video_tabs[cam_name].canvas.setImage(frame)
            
            self.last_framerate = fr
            self.video_tabs[cam_name].framerate_counter.setText('Framerate:\n{:.1f} Hz'.format(fr))

    def update_video_skipstep(self, val):
        self.mutex.lock()
        self.video_skipstep = val
        self.mutex.unlock()