From e191db3cbea409250b8d075d25ffc9dbd7dfbab3 Mon Sep 17 00:00:00 2001 From: Arthur Golubtsov Date: Wed, 25 Sep 2019 16:25:59 +0300 Subject: [PATCH] Server: Add ability to play music --- Server/server_gui.py | 190 +++++++++++++++++++++----------- Server/server_gui.ui | 254 ++++++++++++++++++++++++++++++------------- Server/server_qt.py | 80 +++++++++++++- 3 files changed, 380 insertions(+), 144 deletions(-) diff --git a/Server/server_gui.py b/Server/server_gui.py index a9c4ad0..0826274 100644 --- a/Server/server_gui.py +++ b/Server/server_gui.py @@ -13,7 +13,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1220, 613) + MainWindow.resize(1220, 750) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName("centralwidget") @@ -43,31 +43,41 @@ class Ui_MainWindow(object): self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetMaximumSize) self.verticalLayout.setObjectName("verticalLayout") self.formLayout = QtWidgets.QFormLayout() - self.formLayout.setLabelAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.formLayout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.formLayout.setLabelAlignment(QtCore.Qt.AlignCenter) + self.formLayout.setFormAlignment(QtCore.Qt.AlignCenter) self.formLayout.setObjectName("formLayout") - self.check_button = QtWidgets.QPushButton(self.centralwidget) - self.check_button.setEnabled(True) - self.check_button.setObjectName("check_button") - self.formLayout.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.check_button) - self.start_text = QtWidgets.QLabel(self.centralwidget) - self.start_text.setAlignment(QtCore.Qt.AlignCenter) - self.start_text.setObjectName("start_text") - self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.start_text) + self.music_text = QtWidgets.QLabel(self.centralwidget) + self.music_text.setLayoutDirection(QtCore.Qt.RightToLeft) + self.music_text.setObjectName("music_text") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.music_text) + self.music_delay_spin = QtWidgets.QDoubleSpinBox(self.centralwidget) + self.music_delay_spin.setDecimals(1) + self.music_delay_spin.setObjectName("music_delay_spin") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.music_delay_spin) + self.music_checkbox = QtWidgets.QCheckBox(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.music_checkbox.sizePolicy().hasHeightForWidth()) + self.music_checkbox.setSizePolicy(sizePolicy) + self.music_checkbox.setLayoutDirection(QtCore.Qt.RightToLeft) + self.music_checkbox.setAutoFillBackground(True) + self.music_checkbox.setText("") + self.music_checkbox.setChecked(False) + self.music_checkbox.setObjectName("music_checkbox") + self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.music_checkbox) + self.music_play_text = QtWidgets.QLabel(self.centralwidget) + self.music_play_text.setLayoutDirection(QtCore.Qt.RightToLeft) + self.music_play_text.setObjectName("music_play_text") + self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.music_play_text) self.start_delay_spin = QtWidgets.QSpinBox(self.centralwidget) self.start_delay_spin.setObjectName("start_delay_spin") self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.start_delay_spin) - self.start_button = QtWidgets.QPushButton(self.centralwidget) - self.start_button.setEnabled(True) - self.start_button.setFlat(False) - self.start_button.setObjectName("start_button") - self.formLayout.setWidget(3, QtWidgets.QFormLayout.SpanningRole, self.start_button) - self.pause_button = QtWidgets.QPushButton(self.centralwidget) - self.pause_button.setObjectName("pause_button") - self.formLayout.setWidget(4, QtWidgets.QFormLayout.SpanningRole, self.pause_button) - self.stop_button = QtWidgets.QPushButton(self.centralwidget) - self.stop_button.setObjectName("stop_button") - self.formLayout.setWidget(5, QtWidgets.QFormLayout.SpanningRole, self.stop_button) + self.start_text = QtWidgets.QLabel(self.centralwidget) + self.start_text.setLayoutDirection(QtCore.Qt.RightToLeft) + self.start_text.setAlignment(QtCore.Qt.AlignCenter) + self.start_text.setObjectName("start_text") + self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.start_text) self.verticalLayout.addLayout(self.formLayout) self.line = QtWidgets.QFrame(self.centralwidget) self.line.setFrameShape(QtWidgets.QFrame.HLine) @@ -77,15 +87,21 @@ class Ui_MainWindow(object): self.formLayout_2 = QtWidgets.QFormLayout() self.formLayout_2.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.formLayout_2.setObjectName("formLayout_2") - self.disarm_button = QtWidgets.QPushButton(self.centralwidget) - self.disarm_button.setObjectName("disarm_button") - self.formLayout_2.setWidget(7, QtWidgets.QFormLayout.SpanningRole, self.disarm_button) - self.emergency_button = QtWidgets.QPushButton(self.centralwidget) - self.emergency_button.setObjectName("emergency_button") - self.formLayout_2.setWidget(6, QtWidgets.QFormLayout.SpanningRole, self.emergency_button) - self.disarm_all_button = QtWidgets.QPushButton(self.centralwidget) - self.disarm_all_button.setObjectName("disarm_all_button") - self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.SpanningRole, self.disarm_all_button) + self.stop_button = QtWidgets.QPushButton(self.centralwidget) + self.stop_button.setObjectName("stop_button") + self.formLayout_2.setWidget(10, QtWidgets.QFormLayout.FieldRole, self.stop_button) + self.pause_button = QtWidgets.QPushButton(self.centralwidget) + self.pause_button.setObjectName("pause_button") + self.formLayout_2.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.pause_button) + self.start_button = QtWidgets.QPushButton(self.centralwidget) + self.start_button.setEnabled(True) + self.start_button.setFlat(False) + self.start_button.setObjectName("start_button") + self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.start_button) + self.check_button = QtWidgets.QPushButton(self.centralwidget) + self.check_button.setEnabled(True) + self.check_button.setObjectName("check_button") + self.formLayout_2.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.check_button) self.verticalLayout.addLayout(self.formLayout_2) self.line_2 = QtWidgets.QFrame(self.centralwidget) self.line_2.setFrameShape(QtWidgets.QFrame.HLine) @@ -96,19 +112,15 @@ class Ui_MainWindow(object): self.formLayout_3.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.formLayout_3.setVerticalSpacing(6) self.formLayout_3.setObjectName("formLayout_3") - self.leds_button = QtWidgets.QPushButton(self.centralwidget) - self.leds_button.setObjectName("leds_button") - self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.leds_button) - self.takeoff_button = QtWidgets.QPushButton(self.centralwidget) - self.takeoff_button.setEnabled(True) - self.takeoff_button.setObjectName("takeoff_button") - self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.takeoff_button) - self.flip_button = QtWidgets.QPushButton(self.centralwidget) - self.flip_button.setObjectName("flip_button") - self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.flip_button) - self.land_button = QtWidgets.QPushButton(self.centralwidget) - self.land_button.setObjectName("land_button") - self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.SpanningRole, self.land_button) + self.disarm_all_button = QtWidgets.QPushButton(self.centralwidget) + self.disarm_all_button.setObjectName("disarm_all_button") + self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.disarm_all_button) + self.disarm_button = QtWidgets.QPushButton(self.centralwidget) + self.disarm_button.setObjectName("disarm_button") + self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.disarm_button) + self.emergency_button = QtWidgets.QPushButton(self.centralwidget) + self.emergency_button.setObjectName("emergency_button") + self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.emergency_button) self.verticalLayout.addLayout(self.formLayout_3) self.line_3 = QtWidgets.QFrame(self.centralwidget) self.line_3.setFrameShape(QtWidgets.QFrame.HLine) @@ -116,18 +128,40 @@ class Ui_MainWindow(object): self.line_3.setObjectName("line_3") self.verticalLayout.addWidget(self.line_3) self.formLayout_4 = QtWidgets.QFormLayout() - self.formLayout_4.setFormAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft) + self.formLayout_4.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.formLayout_4.setObjectName("formLayout_4") + self.land_button = QtWidgets.QPushButton(self.centralwidget) + self.land_button.setObjectName("land_button") + self.formLayout_4.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.land_button) + self.flip_button = QtWidgets.QPushButton(self.centralwidget) + self.flip_button.setObjectName("flip_button") + self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.flip_button) + self.takeoff_button = QtWidgets.QPushButton(self.centralwidget) + self.takeoff_button.setEnabled(True) + self.takeoff_button.setObjectName("takeoff_button") + self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.takeoff_button) + self.leds_button = QtWidgets.QPushButton(self.centralwidget) + self.leds_button.setObjectName("leds_button") + self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.leds_button) + self.verticalLayout.addLayout(self.formLayout_4) + self.line_4 = QtWidgets.QFrame(self.centralwidget) + self.line_4.setFrameShape(QtWidgets.QFrame.HLine) + self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line_4.setObjectName("line_4") + self.verticalLayout.addWidget(self.line_4) + self.formLayout_6 = QtWidgets.QFormLayout() + self.formLayout_6.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.formLayout_6.setObjectName("formLayout_6") self.reboot_fcu = QtWidgets.QPushButton(self.centralwidget) self.reboot_fcu.setObjectName("reboot_fcu") - self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.reboot_fcu) + self.formLayout_6.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.reboot_fcu) self.calibrate_gyro = QtWidgets.QPushButton(self.centralwidget) self.calibrate_gyro.setObjectName("calibrate_gyro") - self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.calibrate_gyro) + self.formLayout_6.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.calibrate_gyro) self.calibrate_level = QtWidgets.QPushButton(self.centralwidget) self.calibrate_level.setObjectName("calibrate_level") - self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.calibrate_level) - self.verticalLayout.addLayout(self.formLayout_4) + self.formLayout_6.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.calibrate_level) + self.verticalLayout.addLayout(self.formLayout_6) self.horizontalLayout.addLayout(self.verticalLayout) self.horizontalLayout.setStretch(0, 1) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) @@ -143,6 +177,10 @@ class Ui_MainWindow(object): self.menuTable.setObjectName("menuTable") self.menuAnimation = QtWidgets.QMenu(self.menubar) self.menuAnimation.setObjectName("menuAnimation") + self.menuDrone = QtWidgets.QMenu(self.menubar) + self.menuDrone.setObjectName("menuDrone") + self.menuMusic = QtWidgets.QMenu(self.menubar) + self.menuMusic.setObjectName("menuMusic") MainWindow.setMenuBar(self.menubar) self.action_send_animations = QtWidgets.QAction(MainWindow) self.action_send_animations.setObjectName("action_send_animations") @@ -166,6 +204,16 @@ class Ui_MainWindow(object): self.action_set_start_to_current_position.setObjectName("action_set_start_to_current_position") self.action_reset_start = QtWidgets.QAction(MainWindow) self.action_reset_start.setObjectName("action_reset_start") + self.action_set_z_offset_to_ground = QtWidgets.QAction(MainWindow) + self.action_set_z_offset_to_ground.setObjectName("action_set_z_offset_to_ground") + self.action_reset_z_offset = QtWidgets.QAction(MainWindow) + self.action_reset_z_offset.setObjectName("action_reset_z_offset") + self.action_select_music_file = QtWidgets.QAction(MainWindow) + self.action_select_music_file.setObjectName("action_select_music_file") + self.action_play_music = QtWidgets.QAction(MainWindow) + self.action_play_music.setObjectName("action_play_music") + self.action_test_music_after = QtWidgets.QAction(MainWindow) + self.action_test_music_after.setObjectName("action_test_music_after") self.menuDeveloper_mode.addAction(self.action_send_launch_file) self.menuDeveloper_mode.addAction(self.action_restart_clever) self.menuDeveloper_mode.addAction(self.action_restart_clever_show) @@ -178,35 +226,40 @@ class Ui_MainWindow(object): self.menuTable.addAction(self.action_select_all_rows) self.menuAnimation.addAction(self.action_set_start_to_current_position) self.menuAnimation.addAction(self.action_reset_start) + self.menuDrone.addAction(self.action_set_z_offset_to_ground) + self.menuDrone.addAction(self.action_reset_z_offset) + self.menuMusic.addAction(self.action_select_music_file) + self.menuMusic.addAction(self.action_play_music) + self.menuMusic.addAction(self.action_test_music_after) self.menubar.addAction(self.menuOptions.menuAction()) self.menubar.addAction(self.menuAnimation.menuAction()) + self.menubar.addAction(self.menuDrone.menuAction()) + self.menubar.addAction(self.menuMusic.menuAction()) self.menubar.addAction(self.menuTable.menuAction()) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) - MainWindow.setTabOrder(self.check_button, self.start_delay_spin) - MainWindow.setTabOrder(self.start_delay_spin, self.start_button) - MainWindow.setTabOrder(self.start_button, self.pause_button) - MainWindow.setTabOrder(self.pause_button, self.stop_button) - MainWindow.setTabOrder(self.stop_button, self.disarm_button) - MainWindow.setTabOrder(self.disarm_button, self.tableView) + MainWindow.setTabOrder(self.start_delay_spin, self.tableView) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Clever Drone Animation Player")) - self.check_button.setText(_translate("MainWindow", "Preflight check")) - self.start_text.setText(_translate("MainWindow", "Start after")) - self.start_delay_spin.setSuffix(_translate("MainWindow", " seconds")) - self.start_button.setText(_translate("MainWindow", "Start animation")) - self.pause_button.setText(_translate("MainWindow", "Pause")) + self.music_text.setText(_translate("MainWindow", " Music after")) + self.music_delay_spin.setSuffix(_translate("MainWindow", " s")) + self.music_play_text.setText(_translate("MainWindow", " Play music")) + self.start_delay_spin.setSuffix(_translate("MainWindow", " s")) + self.start_text.setText(_translate("MainWindow", " Start after")) self.stop_button.setText(_translate("MainWindow", "Stop and land all")) + self.pause_button.setText(_translate("MainWindow", "Pause")) + self.start_button.setText(_translate("MainWindow", "Start animation")) + self.check_button.setText(_translate("MainWindow", "Preflight check")) + self.disarm_all_button.setText(_translate("MainWindow", "Disarm ALL")) self.disarm_button.setText(_translate("MainWindow", "Disarm selected")) self.emergency_button.setText(_translate("MainWindow", "Emergency land")) - self.disarm_all_button.setText(_translate("MainWindow", "Disarm ALL")) - self.leds_button.setText(_translate("MainWindow", "Test leds")) - self.takeoff_button.setText(_translate("MainWindow", "Takeoff")) - self.flip_button.setText(_translate("MainWindow", "Flip")) self.land_button.setText(_translate("MainWindow", "Land")) + self.flip_button.setText(_translate("MainWindow", "Flip")) + self.takeoff_button.setText(_translate("MainWindow", "Takeoff")) + self.leds_button.setText(_translate("MainWindow", "Test leds")) self.reboot_fcu.setText(_translate("MainWindow", "Reboot FCU")) self.calibrate_gyro.setText(_translate("MainWindow", "Calibrate gyro")) self.calibrate_level.setText(_translate("MainWindow", "Calibrate level")) @@ -214,6 +267,8 @@ class Ui_MainWindow(object): self.menuDeveloper_mode.setTitle(_translate("MainWindow", "Developer mode")) self.menuTable.setTitle(_translate("MainWindow", "Table")) self.menuAnimation.setTitle(_translate("MainWindow", "Animation")) + self.menuDrone.setTitle(_translate("MainWindow", "Drone")) + self.menuMusic.setTitle(_translate("MainWindow", "Music")) self.action_send_animations.setText(_translate("MainWindow", "Send Animations")) self.action_send_configurations.setText(_translate("MainWindow", "Send Configurations")) self.action_send_Aruco_map.setText(_translate("MainWindow", "Send Aruco map")) @@ -224,5 +279,10 @@ class Ui_MainWindow(object): self.action_restart_clever_show.setText(_translate("MainWindow", "Restart clever-show service")) self.action_select_all_rows.setText(_translate("MainWindow", "Select All")) self.action_select_all_rows.setShortcut(_translate("MainWindow", "Ctrl+A")) - self.action_set_start_to_current_position.setText(_translate("MainWindow", "Set start to current position")) + self.action_set_start_to_current_position.setText(_translate("MainWindow", "Set start X Y to current position")) self.action_reset_start.setText(_translate("MainWindow", "Reset start position")) + self.action_set_z_offset_to_ground.setText(_translate("MainWindow", "Set Z offset to ground")) + self.action_reset_z_offset.setText(_translate("MainWindow", "Reset Z offset")) + self.action_select_music_file.setText(_translate("MainWindow", "Select music file")) + self.action_play_music.setText(_translate("MainWindow", "Play music")) + self.action_test_music_after.setText(_translate("MainWindow", "Test music after")) diff --git a/Server/server_gui.ui b/Server/server_gui.ui index 4c45f2d..abeb6af 100644 --- a/Server/server_gui.ui +++ b/Server/server_gui.ui @@ -7,7 +7,7 @@ 0 0 1220 - 613 + 750 @@ -68,62 +68,80 @@ - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignCenter - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignCenter - - - - true + + + + Qt::RightToLeft - Preflight check + Music after - - - - Start after + + + + s - - Qt::AlignCenter + + 1 + + + + + + + + 0 + 0 + + + + Qt::RightToLeft + + + true + + + + + + false + + + + + + + Qt::RightToLeft + + + Play music - seconds + s - - - - true + + + + Qt::RightToLeft - Start animation + Start after - - false - - - - - - - Pause - - - - - - - Stop and land all + + Qt::AlignCenter @@ -141,24 +159,40 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - Disarm selected + Stop and land all - - + + - Emergency land + Pause - - + + + + true + - Disarm ALL + Start animation + + + false + + + + + + + true + + + Preflight check @@ -179,34 +213,24 @@ 6 - - + + - Test leds + Disarm ALL - - - - true - + + - Takeoff + Disarm selected - - + + - Flip - - - - - - - Land + Emergency land @@ -222,23 +246,68 @@ - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + + + + Land + + + + + + + Flip + + + + + + + true + + + Takeoff + + + + + + + Test leds + + + + + + + + + Qt::Horizontal + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + Reboot FCU - + Calibrate gyro - + Calibrate level @@ -294,8 +363,25 @@ + + + Drone + + + + + + + Music + + + + + + + @@ -348,7 +434,7 @@ - Set start to current position + Set start X Y to current position @@ -356,14 +442,34 @@ Reset start position + + + Set Z offset to ground + + + + + Reset Z offset + + + + + Select music file + + + + + Play music + + + + + Test music after + + - check_button start_delay_spin - start_button - pause_button - stop_button - disarm_button tableView diff --git a/Server/server_qt.py b/Server/server_qt.py index 3ba0fe9..898a9d4 100644 --- a/Server/server_qt.py +++ b/Server/server_qt.py @@ -1,12 +1,14 @@ import os import glob import math +import asyncio -from PyQt5 import QtWidgets +from PyQt5 import QtWidgets, QtMultimedia from PyQt5.QtGui import QStandardItemModel, QStandardItem -from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal, QObject +from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal, QObject, QUrl from PyQt5.QtWidgets import QFileDialog, QMessageBox +from quamash import QEventLoop # Importing gui form from server_gui import Ui_MainWindow @@ -17,6 +19,16 @@ from emergency import * import threading +def wait(end, interrupter=threading.Event(), maxsleep=0.1): + # Added features to interrupter sleep and set max sleeping interval + + while not interrupter.is_set(): # Basic implementation of pause module until() + now = time.time() + diff = min(end - now, maxsleep) + if diff <= 0: + break + else: + time.sleep(diff / 2) def confirmation_required(text="Are you sure?", label="Confirm operation?"): def inner(f): @@ -41,7 +53,7 @@ def confirmation_required(text="Are you sure?", label="Confirm operation?"): # noinspection PyArgumentList,PyCallByClass class MainWindow(QtWidgets.QMainWindow): - def __init__(self): + def __init__(self, loop): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() @@ -54,6 +66,8 @@ class MainWindow(QtWidgets.QMainWindow): self.gyro_calibrated = {} self.level_calibrated = {} self.first_col_is_checked = False + self.player = QtMultimedia.QMediaPlayer() + self.loop = loop self.init_model() @@ -123,6 +137,9 @@ class MainWindow(QtWidgets.QMainWindow): self.ui.action_update_client_repo.triggered.connect(self.update_client_repo) self.ui.action_set_start_to_current_position.triggered.connect(self.update_start_to_current_position) self.ui.action_reset_start.triggered.connect(self.reset_start) + self.ui.action_select_music_file.triggered.connect(self.select_music_file) + self.ui.action_play_music.triggered.connect(self.play_music) + self.ui.action_test_music_after.triggered.connect(self.test_music_after) # Set most safety-important buttons disabled self.ui.start_button.setEnabled(False) @@ -178,6 +195,11 @@ class MainWindow(QtWidgets.QMainWindow): @pyqtSlot() def send_starttime_selected(self, **kwargs): dt = self.ui.start_delay_spin.value() + logging.info('Wait {} seconds to start animation'.format(dt)) + if self.ui.music_checkbox.checked: + music_dt = self.ui.music_delay_spin.value() + asyncio.ensure_future(self.play_music_after(music_dt), loop=self.loop) + logging.info('Wait {} seconds to play music'.format(music_dt)) self.selfcheck_selected() for copter in self.model.user_selected(): if all_checks(copter): @@ -351,6 +373,49 @@ class MainWindow(QtWidgets.QMainWindow): for copter in self.model.user_selected(): copter.client.send_message("reset_start") + @pyqtSlot() + def select_music_file(self): + path = QFileDialog.getOpenFileName(self, "Select music file", filter="Music files (*.mp3)")[0] + if path: + media = QUrl.fromLocalFile(path) + content = QtMultimedia.QMediaContent(media) + self.player.setMedia(content) + + @pyqtSlot() + def play_music(self): + if self.player.mediaStatus() == QtMultimedia.QMediaPlayer.InvalidMedia: + logger.info("Can't play media") + return + if self.player.mediaStatus() == QtMultimedia.QMediaPlayer.NoMedia: + logger.info("No media file") + return + + if self.player.state() == QtMultimedia.QMediaPlayer.StoppedState or \ + self.player.state() == QtMultimedia.QMediaPlayer.PausedState: + self.player.play() + else: + self.player.pause() + + + @asyncio.coroutine + def play_music_after(self, delay=0.): + if self.player.mediaStatus() == QtMultimedia.QMediaPlayer.InvalidMedia: + logger.info("Can't play media") + return + if self.player.mediaStatus() == QtMultimedia.QMediaPlayer.NoMedia: + logger.info("No media file") + return + self.player.stop() + wait(time.time()+delay) + logging.info("Play music") + self.player.play() + + @pyqtSlot() + def test_music_after(self): + dt = self.ui.music_delay_spin.value() + asyncio.ensure_future(self.play_music_after(dt), loop=self.loop) + logging.info('Wait {} seconds to play music'.format(dt)) + @pyqtSlot() def emergency(self): client_row_min = 0 @@ -401,13 +466,18 @@ class MainWindow(QtWidgets.QMainWindow): if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) - window = MainWindow() + loop = QEventLoop(app) + asyncio.set_event_loop(loop) + window = MainWindow(loop) Client.on_first_connect = window.client_connected server = Server(on_stop=app.quit) server.start() - app.exec_() + #app.exec_() + with loop: + loop.run_forever() + server.stop() sys.exit()