class VideoPlayer(QtWidgets.QWidget): def __init__(self, url: str): super(VideoPlayer, self).__init__() self.player = QMediaPlayer() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.playlist = QMediaPlaylist(self.player) self.playlist.addMedia(QUrl(url)) self.video_widget = QVideoWidget() self.player.setVideoOutput(self.video_widget) self.playlist.setCurrentIndex(0) self.player.setPlaylist(self.playlist) self.layout = QtWidgets.QVBoxLayout() self.layout.addWidget(self.video_widget) self.setLayout(self.layout) self.player.play() QApplication.restoreOverrideCursor() def mousePressEvent(self, event): if self.player.state() == QMediaPlayer.PausedState: self.player. play() else: self.player.pause()
class ToneBoxApp(QApplication): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.settings_model = SettingsModel() self.manager_model = manager_model.Model( self.settings_model.get("DatabasePath")) self.queue_manager = queue_manager.QueueManager(self.manager_model) self.player_object = QMediaPlayer() self.player_object.setPlaylist(self.queue_manager) self.queue_manager.player_object = self.player_object self.main_window = MainWindow(self.settings_model, self.manager_model, self.queue_manager) self.queue_manager.player_widget = self.main_window.playerWidget self.main_window.playerWidget.queue_manager = self.queue_manager self.queue_manager.queue_widget = self.main_window.queueWidget self.main_window.queueWidget.queue_manager = self.queue_manager self.queue_manager.setup_signals() self.main_window.show()
class VideoMediaView_(MediaView): def __init__(self, media, parent): super(VideoMediaView_, self).__init__(media, parent) self.widget = QVideoWidget(parent) self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.player.setVideoOutput(self.widget) self.widget.setGeometry(media['geometry']) self.set_default_widget_prop() self.widget.setDisabled(True) @Slot() def play(self): self.finished = 0 path = '%s/%s' % (self.save_dir, self.options['uri']) self.playlist.addMedia(QMediaContent(path)) self.player.play() self.widget.show() self.widget.raise_() if float(self.duration) > 0: self.play_timer.setInterval(int(float(self.duration) * 1000)) self.play_timer.start() self.started_signal.emit() @Slot() def stop(self, delete_widget=False): #---- kong ---- if not self.widget: return False self.player.stop() self.playlist = None self.player = None super(VideoMediaView_, self).stop(delete_widget) return True
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) self.videoWidget = QVideoWidget() self.mediaPlayer = QMediaPlayer() self.mediaPlaylist = QMediaPlaylist() # Add the video file path self.mediaPlaylist.addMedia(QUrl.fromLocalFile(os.path.abspath("./sample_data/sampleVideo.mp4"))) # Set the video to played in a loop once it ends. self.mediaPlaylist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) # Set the QMediaPlaylist for the QMediaPlayer. self.mediaPlayer.setPlaylist(self.mediaPlaylist) # Add the QVideoWidget in the GridLayout. self.playerLayout.addWidget(self.videoWidget) # Set the video output from the QMediaPlayer to the QVideoWidget. self.mediaPlayer.setVideoOutput(self.videoWidget) # Set the QPushButtons to play, pause and stop the video in the QVideoWidget. self.playButton.clicked.connect(self.play_video) self.pauseButton.clicked.connect(self.pause_video) self.stopButton.clicked.connect(self.stop_video) # Set the total range for the QSlider. self.mediaPlayer.durationChanged.connect(self.change_duration) # Set the current value for the QSlider. self.mediaPlayer.positionChanged.connect(self.change_position) # Set the video position in QMediaPlayer based on the QSlider position. self.horizontalSlider.sliderMoved.connect(self.video_position) def play_video(self): """ Handles the clicked signal generated by playButton and plays the video in the mediaPlayer. """ self.mediaPlayer.play() def pause_video(self): """ Handles the clicked signal generated by playButton and pauses video in the mediaPlayer. """ self.mediaPlayer.pause() def stop_video(self): """ Handles the clicked signal generated by playButton and stops the video in the mediaPlayer. """ self.mediaPlayer.stop() def change_position(self, position): """ Handles the positionChanged signal generated by the mediaPlayer. Sets the current value of the QSlider to the current position of the video in the QMediaPlayer. :param position: current position of the video in the QMediaPlayer. """ self.horizontalSlider.setValue(position) def change_duration(self, duration): """ Handles the durationChanged signal generated by the mediaPlayer. Sets the range of the QSlider. :param duration: Total duration of the video in the QMediaPlayer. """ self.horizontalSlider.setRange(0, duration) def video_position(self, position): """ Handles the sliderMoved signal generated by the horizontalSlider. Changes the position of the video in the QMediaPlayer on changing the value of the QSlider. :param position: Current position value of the QSlider. :return: """ self.mediaPlayer.setPosition(position)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.player = QMediaPlayer() self.playlist = QMediaPlaylist() toolBar = QToolBar() self.addToolBar(toolBar) playIcon = self.style().standardIcon(QStyle.SP_MediaPlay) previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward) nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward) pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause) stopIcon = self.style().standardIcon(QStyle.SP_MediaStop) self.playAction = toolBar.addAction(playIcon, "Play") self.previousAction = toolBar.addAction(previousIcon, "Previous") self.nextAction = toolBar.addAction(nextIcon, "Next") self.pauseAction = toolBar.addAction(pauseIcon, "Pause") self.stopAction = toolBar.addAction(stopIcon, "Stop") self.playAction.triggered.connect(self.player.play) self.previousAction.triggered.connect(self.previousClicked) self.nextAction.triggered.connect(self.playlist.next) self.pauseAction.triggered.connect(self.player.pause) self.stopAction.triggered.connect(self.player.stop) self.volSlider = QSlider() self.volSlider.setOrientation(Qt.Horizontal) self.volSlider.setMinimum(0) self.volSlider.setMaximum(100) self.volSlider.setFixedWidth(120) self.volSlider.setValue(self.player.volume()) self.volSlider.setTickInterval(10) self.volSlider.setTickPosition(QSlider.TicksBelow) self.volSlider.setToolTip("Volume") self.volSlider.valueChanged.connect(self.player.setVolume) toolBar.addWidget(self.volSlider) openAction = QAction(QIcon.fromTheme("document-open"), "&Open...", self, shortcut=QKeySequence.Open, triggered=self.open) exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit", self, shortcut="Ctrl+Q", triggered=self.close) aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt) fileMenu = self.menuBar().addMenu("&File") fileMenu.addAction(openAction) fileMenu.addAction(exitAction) playMenu = self.menuBar().addMenu("&Play") playMenu.addAction(self.playAction) playMenu.addAction(self.previousAction) playMenu.addAction(self.nextAction) playMenu.addAction(self.pauseAction) playMenu.addAction(self.stopAction) aboutMenu = self.menuBar().addMenu("&About") aboutMenu.addAction(aboutQtAct) self.videoWidget = QVideoWidget() self.setCentralWidget(self.videoWidget) self.player.setPlaylist(self.playlist) self.player.stateChanged.connect(self.updateButtons) self.player.setVideoOutput(self.videoWidget) self.updateButtons(self.player.state()) def open(self): fileDialog = QFileDialog(self) supportedMimeTypes = ["video/mp4", "*.*"] fileDialog.setMimeTypeFilters(supportedMimeTypes) moviesLocation = QStandardPaths.writableLocation( QStandardPaths.MoviesLocation) fileDialog.setDirectory(moviesLocation) if fileDialog.exec_() == QDialog.Accepted: self.playlist.addMedia(fileDialog.selectedUrls()[0]) self.player.play() def previousClicked(self): if self.player.position() <= 5000: self.playlist.previous() else: player.setPosition(0) def updateButtons(self, state): mediaCount = self.playlist.mediaCount() self.playAction.setEnabled(mediaCount > 0 and state != QMediaPlayer.PlayingState) self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState) self.stopAction.setEnabled(state != QMediaPlayer.StoppedState) self.previousAction.setEnabled(self.player.position() > 0) self.nextAction.setEnabled(mediaCount > 1)
class MainWindow(QMainWindow): def __init__(self): global pixmapDict, specialDescriptionDict super(MainWindow, self).__init__() self.ui = Ui_pipboy() self.ui.setupUi(self) self.ui.chartContainer.setContentsMargins(0, 0, 0, 0) self.anim = QTimeLine(20000, self) self.anim.setFrameRange(0, 500) self.anim.setLoopCount(0) self.anim.setUpdateInterval(16) self.anim.frameChanged[int].connect( self.ui.perks_description.verticalScrollBar().setValue) self.anim.frameChanged[int].connect( self.ui.aid_effect_label.verticalScrollBar().setValue) self.anim.frameChanged[int].connect( self.ui.data_description.verticalScrollBar().setValue) #self.anim2 = QPropertyAnimation(self.ui.main_tab, b"pos") #self.anim2.setEasingCurve(QEasingCurve.OutBounce) #self.anim2.setDuration(2000) #self.anim2.setStartValue(QPoint(10, -400)) #self.anim2.setEndValue(QPoint(10, 0)) #self.anim2.start() self.random = QRandomGenerator.global_() self.ui.stat_tab.setFocus() self.ui.stat_tab.currentChanged.connect(self.shift) self.ui.stat_tab.installEventFilter(self) self.ui.inv_tab.installEventFilter(self) self.ui.special_list.installEventFilter(self) self.ui.perks_list.installEventFilter(self) self.ui.test_list.installEventFilter(self) self.ui.apparel_list.installEventFilter(self) self.ui.aid_list.installEventFilter(self) self.ui.ammo_list.installEventFilter(self) self.ui.data_list.installEventFilter(self) self.ui.radio_list.installEventFilter(self) self.ui.main_img.setPixmap(description.main_img_pixmap) self.ui.special_image.setPixmap(description.pixmapDict.get(0)) self.ui.perks_image.setPixmap(description.pixmatPerksDict.get(0)) self.ui.weapon_image.setPixmap(description.pixmapWeaponDict.get(0)) self.ui.apparel_image.setPixmap(description.pixmapWeaponDict.get(0)) self.ui.aid_image.setPixmap(description.pixmapAidDict.get(0)) self.ui.ammo_image.setPixmap(description.pixmapAmmoDict.get(0)) lay = QVBoxLayout(self.ui.chartContainer) lay.setContentsMargins(0, 0, 0, 0) self.chartview = QtCharts.QChartView() self.chartview.setContentsMargins(0, 0, 0, 0) lay.addWidget(self.chartview) self.chart = QtCharts.QChart() self.chart.legend().hide() self.chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations) self.series = QtCharts.QLineSeries() self.pen = QPen(QColor(119, 251, 81, 255)) self.pen.setWidth(3) self.pen.setJoinStyle(Qt.RoundJoin) self.series.setPen(self.pen) backgroundGradient = QLinearGradient(QPointF(100, 100), QPointF(200, 200)) backgroundGradient.setColorAt(0, QColor(0, 0, 0, 255)) backgroundGradient.setColorAt(1, QColor(0, 0, 0, 255)) self.chart.setBackgroundBrush(backgroundGradient) self.chart.setPlotAreaBackgroundBrush(backgroundGradient) self.chart.addSeries(self.series) self.chart.createDefaultAxes() self.chart.axisX(self.series).setVisible(False) self.chart.axisY(self.series).setVisible(False) self.chart.axisY(self.series).setRange(0, 100) self.chartview.setChart(self.chart) self.play = False self.player = QMediaPlayer() self.playlistFalloutNewVegas = QMediaPlaylist(self.player) self.playlistFalloutNewVegas.addMedia( QMediaContent(description.falooutNewVegas)) self.playlistFalloutNewVegas.setCurrentIndex(1) self.playListMohaveMusic = QMediaPlaylist(self.player) for url in description.mohaveMusic: self.playListMohaveMusic.addMedia(QMediaContent(url)) self.playListMohaveMusic.setCurrentIndex(1) self.playlisNewVegas = QMediaPlaylist(self.player) for url in description.newVegas: self.playlisNewVegas.addMedia(QMediaContent(url)) self.playlisNewVegas.setCurrentIndex(1) self.playlistDict = { 0: self.playlistFalloutNewVegas, 1: self.playListMohaveMusic, 2: self.playlisNewVegas } def append_data_and_plot(self, d): """Append and update the plot""" num, m = d ax1 = self.chart.axisX(self.series) xmin = xmax = num step = 100 for p in self.series.pointsVector()[-step:]: xmin = min(p.x(), xmin) xmax = max(p.x(), xmax) xmin = max(0, xmax - step) ax1.setMin(xmin) ax1.setMax(xmax) self.series.append(QPointF(num, m)) def eventFilter(self, obj, event): if event.type() == QEvent.KeyPress: #print(obj) if event.key() == 49: self.ui.main_tab.setCurrentIndex(1) self.ui.stat_tab.setFocus() #self.ui.hp_head.setValue(self.random.bounded(50, 100)) #self.ui.hp_left_arm.setValue(self.random.bounded(50, 100)) #self.ui.hp_right_arm.setValue(self.random.bounded(50, 100)) #self.ui.hp_left_leg.setValue(self.random.bounded(50, 100)) #self.ui.hp_right_leg.setValue(self.random.bounded(50, 100)) #self.ui.hp_body.setValue(self.random.bounded(50, 100)) return True elif event.key() == 50: self.ui.main_tab.setCurrentIndex(2) self.ui.inv_tab.setFocus() return True elif event.key() == 51: self.ui.main_tab.setCurrentIndex(3) self.ui.data_list.setFocus() self.ui.data_list.setCurrentRow(0) return True elif event.key() == 52: self.ui.main_tab.setCurrentIndex(4) return True elif event.key() == 53: self.ui.main_tab.setCurrentIndex(5) self.ui.radio_list.setFocus() self.ui.radio_list.setCurrentRow(0) return True elif event.key() == 54: print(QApplication.focusWidget()) return True #focus from stat_tab to special_list elif (obj == self.ui.stat_tab) and (self.ui.stat_tab.currentIndex() == 1) and (event.key() == 47): self.ui.special_list.setFocus() self.ui.special_list.setCurrentRow(0) self.ui.special_image.setPixmap(description.pixmapDict.get(0)) self.ui.special_description.setText( description.specialDescriptionDict.get(0)) return True # elif (obj == self.ui.special_list) and (event.key() == 16777236): self.ui.special_list.setCurrentRow( self.ui.special_list.currentRow() + 1) if (self.ui.special_list.currentRow() == -1): self.ui.special_list.setCurrentRow(0) self.ui.special_list.scrollToItem( self.ui.special_list.currentItem()) self.ui.special_image.setPixmap( description.pixmapDict.get( self.ui.special_list.currentRow())) self.ui.special_description.setText( description.specialDescriptionDict.get( self.ui.special_list.currentRow())) elif (obj == self.ui.special_list) and (event.key() == 16777234): self.ui.special_list.setCurrentRow( self.ui.special_list.currentRow() - 1) if (self.ui.special_list.currentRow() == -1): self.ui.special_list.setCurrentRow(0) self.ui.special_list.scrollToItem( self.ui.special_list.currentItem()) self.ui.special_image.setPixmap( description.pixmapDict.get( self.ui.special_list.currentRow())) self.ui.special_description.setText( description.specialDescriptionDict.get( self.ui.special_list.currentRow())) #focus from special_list to stat_tab elif (obj == self.ui.special_list) and (event.key() == 47): self.ui.special_list.setCurrentRow(-1) self.ui.stat_tab.setFocus() return True # focus from stat_tab to perks_list elif (obj == self.ui.stat_tab) and (self.ui.stat_tab.currentIndex() == 2) and (event.key() == 47): self.ui.perks_list.setFocus() self.ui.perks_list.setCurrentRow(0) self.anim.setCurrentTime(0) self.anim.start() elif (obj == self.ui.perks_list) and (event.key() == 16777236): self.ui.perks_list.setCurrentRow( self.ui.perks_list.currentRow() + 1) if (self.ui.perks_list.currentRow() == -1): self.ui.perks_list.setCurrentRow(0) self.ui.perks_list.scrollToItem( self.ui.perks_list.currentItem()) self.ui.perks_image.setPixmap( description.pixmatPerksDict.get( self.ui.perks_list.currentRow())) self.ui.perks_description.setText( description.perksDescriptionDict.get( self.ui.perks_list.currentRow())) self.anim.stop() self.anim.setCurrentTime(0) self.anim.start() elif (obj == self.ui.perks_list) and (event.key() == 16777234): self.ui.perks_list.setCurrentRow( self.ui.perks_list.currentRow() - 1) if (self.ui.perks_list.currentRow() == -1): self.ui.perks_list.setCurrentRow(0) self.ui.perks_list.scrollToItem( self.ui.perks_list.currentItem()) self.ui.perks_image.setPixmap( description.pixmatPerksDict.get( self.ui.perks_list.currentRow())) self.ui.perks_description.setText( description.perksDescriptionDict.get( self.ui.perks_list.currentRow())) self.anim.stop() self.anim.setCurrentTime(0) self.anim.start() #focus from perks_list to stat_tab elif (obj == self.ui.perks_list) and (event.key() == 47): self.ui.perks_list.setCurrentRow(-1) self.ui.stat_tab.setFocus() self.anim.stop() return True #/------------------------------------------------INV-WEAPON--------------------------------------------------/ elif (obj == self.ui.inv_tab) and (self.ui.inv_tab.currentIndex() == 0) and (event.key() == 47): self.ui.test_list.setFocus() self.ui.test_list.setCurrentRow(0) return True elif (obj == self.ui.test_list) and (event.key() == 47): self.ui.test_list.setCurrentRow(-1) self.ui.inv_tab.setFocus() return True elif (obj == self.ui.test_list) and (event.key() == 16777236): self.ui.test_list.setCurrentRow( self.ui.test_list.currentRow() + 1) if (self.ui.test_list.currentRow() == -1): self.ui.test_list.setCurrentRow(0) self.ui.test_list.scrollToItem(self.ui.test_list.currentItem()) self.ui.weapon_image.setPixmap( description.pixmapWeaponDict.get( self.ui.test_list.currentRow())) self.ui.w_damage_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[0]) self.ui.w_weight_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[1]) self.ui.w_cost_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[2]) self.ui.w_durability_PB.setValue(self.random.bounded(20, 100)) self.ui.w_ammo_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[3]) self.ui.w_effect_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[4]) elif (obj == self.ui.test_list) and (event.key() == 16777234): self.ui.test_list.setCurrentRow( self.ui.test_list.currentRow() - 1) if (self.ui.test_list.currentRow() == -1): self.ui.test_list.setCurrentRow(0) self.ui.test_list.scrollToItem(self.ui.test_list.currentItem()) self.ui.weapon_image.setPixmap( description.pixmapWeaponDict.get( self.ui.test_list.currentRow())) self.ui.w_damage_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[0]) self.ui.w_weight_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[1]) self.ui.w_cost_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[2]) self.ui.w_durability_PB.setValue(self.random.bounded(20, 100)) self.ui.w_ammo_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[3]) self.ui.w_effect_label.setText( description.weaponDescriptionDict.get( self.ui.test_list.currentRow())[4]) #/------------------------------------------------INV-APPAREL--------------------------------------------------/ elif (obj == self.ui.inv_tab) and (self.ui.inv_tab.currentIndex() == 1) and (event.key() == 47): self.ui.apparel_list.setFocus() self.ui.apparel_list.setCurrentRow(0) return True elif (obj == self.ui.apparel_list) and (event.key() == 47): self.ui.apparel_list.setCurrentRow(-1) self.ui.inv_tab.setFocus() return True elif (obj == self.ui.apparel_list) and (event.key() == 16777236): self.ui.apparel_list.setCurrentRow( self.ui.apparel_list.currentRow() + 1) if (self.ui.apparel_list.currentRow() == -1): self.ui.apparel_list.setCurrentRow(0) self.ui.apparel_list.scrollToItem( self.ui.apparel_list.currentItem()) self.ui.apparel_image.setPixmap( description.pixmapClothesDict.get( self.ui.apparel_list.currentRow())) self.ui.a_damage_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[0]) self.ui.a_weight_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[1]) self.ui.a_cost_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[2]) self.ui.a_durability_PB.setValue(self.random.bounded(0, 100)) self.ui.a_type_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[3]) self.ui.a_effect_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[4]) elif (obj == self.ui.apparel_list) and (event.key() == 16777234): self.ui.apparel_list.setCurrentRow( self.ui.apparel_list.currentRow() - 1) if (self.ui.apparel_list.currentRow() == -1): self.ui.apparel_list.setCurrentRow(0) self.ui.apparel_list.scrollToItem( self.ui.apparel_list.currentItem()) self.ui.apparel_image.setPixmap( description.pixmapClothesDict.get( self.ui.apparel_list.currentRow())) self.ui.a_damage_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[0]) self.ui.a_weight_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[1]) self.ui.a_cost_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[2]) self.ui.a_durability_PB.setValue(self.random.bounded(0, 100)) self.ui.a_type_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[3]) self.ui.a_effect_label.setText( description.clothesDescriptionDict.get( self.ui.apparel_list.currentRow())[4]) #/------------------------------------------------INV-AID--------------------------------------------------/ elif (obj == self.ui.inv_tab) and (self.ui.inv_tab.currentIndex() == 2) and (event.key() == 47): self.ui.aid_list.setFocus() self.ui.aid_list.setCurrentRow(0) return True elif (obj == self.ui.aid_list) and (event.key() == 47): self.ui.aid_list.setCurrentRow(-1) self.ui.inv_tab.setFocus() return True elif (obj == self.ui.aid_list) and (event.key() == 16777236): self.ui.aid_list.setCurrentRow(self.ui.aid_list.currentRow() + 1) if (self.ui.aid_list.currentRow() == -1): self.ui.aid_list.setCurrentRow(0) self.ui.aid_list.scrollToItem(self.ui.aid_list.currentItem()) self.ui.aid_image.setPixmap( description.pixmapAidDict.get( self.ui.aid_list.currentRow())) self.ui.aid_weight_label.setText( description.aidDescriptionDict.get( self.ui.aid_list.currentRow())[0]) self.ui.aid_cost_label.setText( description.aidDescriptionDict.get( self.ui.aid_list.currentRow())[1]) self.ui.aid_effect_label.setText( description.aidDescriptionDict.get( self.ui.aid_list.currentRow())[2]) self.anim.stop() self.anim.setCurrentTime(0) self.anim.start() elif (obj == self.ui.aid_list) and (event.key() == 16777234): self.ui.aid_list.setCurrentRow(self.ui.aid_list.currentRow() - 1) if (self.ui.aid_list.currentRow() == -1): self.ui.aid_list.setCurrentRow(0) self.ui.aid_list.scrollToItem(self.ui.aid_list.currentItem()) self.ui.aid_image.setPixmap( description.pixmapAidDict.get( self.ui.aid_list.currentRow())) self.ui.aid_weight_label.setText( description.aidDescriptionDict.get( self.ui.aid_list.currentRow())[0]) self.ui.aid_cost_label.setText( description.aidDescriptionDict.get( self.ui.aid_list.currentRow())[1]) self.ui.aid_effect_label.setText( description.aidDescriptionDict.get( self.ui.aid_list.currentRow())[2]) self.anim.stop() self.anim.setCurrentTime(0) self.anim.start() #/------------------------------------------------INV-AMMO--------------------------------------------------/ elif (obj == self.ui.inv_tab) and (self.ui.inv_tab.currentIndex() == 3) and (event.key() == 47): self.ui.ammo_list.setFocus() self.ui.ammo_list.setCurrentRow(0) return True elif (obj == self.ui.ammo_list) and (event.key() == 47): self.ui.ammo_list.setCurrentRow(-1) self.ui.inv_tab.setFocus() return True elif (obj == self.ui.ammo_list) and (event.key() == 16777236): self.ui.ammo_list.setCurrentRow( self.ui.ammo_list.currentRow() + 1) if (self.ui.ammo_list.currentRow() == -1): self.ui.ammo_list.setCurrentRow(0) self.ui.ammo_list.scrollToItem(self.ui.ammo_list.currentItem()) self.ui.ammo_image.setPixmap( description.pixmapAmmoDict.get( self.ui.ammo_list.currentRow())) self.ui.ammo_weight_label.setText( description.ammoDescriptionDict.get( self.ui.ammo_list.currentRow())[0]) self.ui.ammo_cost_label.setText( description.ammoDescriptionDict.get( self.ui.ammo_list.currentRow())[1]) elif (obj == self.ui.ammo_list) and (event.key() == 16777234): self.ui.ammo_list.setCurrentRow( self.ui.ammo_list.currentRow() - 1) if (self.ui.ammo_list.currentRow() == -1): self.ui.ammo_list.setCurrentRow(0) self.ui.ammo_list.scrollToItem(self.ui.ammo_list.currentItem()) self.ui.ammo_image.setPixmap( description.pixmapAmmoDict.get( self.ui.ammo_list.currentRow())) self.ui.ammo_weight_label.setText( description.ammoDescriptionDict.get( self.ui.ammo_list.currentRow())[0]) self.ui.ammo_cost_label.setText( description.ammoDescriptionDict.get( self.ui.ammo_list.currentRow())[1]) #/------------------------------------------------DATA--------------------------------------------------/ elif (obj == self.ui.data_list) and (event.key() == 16777236): self.ui.data_list.setCurrentRow( self.ui.data_list.currentRow() + 1) if (self.ui.data_list.currentRow() == -1): self.ui.data_list.setCurrentRow(0) self.ui.data_list.scrollToItem(self.ui.data_list.currentItem()) self.ui.data_description.setText( description.questDescriptionDict.get( self.ui.data_list.currentRow())) self.anim.stop() self.anim.setCurrentTime(0) self.anim.start() elif (obj == self.ui.data_list) and (event.key() == 16777234): self.ui.data_list.setCurrentRow( self.ui.data_list.currentRow() - 1) if (self.ui.data_list.currentRow() == -1): self.ui.data_list.setCurrentRow(0) self.ui.data_list.scrollToItem(self.ui.data_list.currentItem()) self.ui.data_description.setText( description.questDescriptionDict.get( self.ui.data_list.currentRow())) self.anim.stop() self.anim.setCurrentTime(0) self.anim.start() #/------------------------------------------------RADIO--------------------------------------------------/ elif (obj == self.ui.radio_list) and (event.key() == 16777236): self.ui.radio_list.setCurrentRow( self.ui.radio_list.currentRow() + 1) if (self.ui.radio_list.currentRow() == -1): self.ui.radio_list.setCurrentRow(0) elif (obj == self.ui.radio_list) and (event.key() == 16777234): self.ui.radio_list.setCurrentRow( self.ui.radio_list.currentRow() - 1) if (self.ui.radio_list.currentRow() == -1): self.ui.radio_list.setCurrentRow(0) #self.ui.data_description.setText(description.questDescriptionDict.get(self.ui.radio_list.currentRow())) elif (obj == self.ui.radio_list) and (event.key() == 47): if self.play: self.player.stop() self.play = False else: self.player.setPlaylist( self.playlistDict.get(self.ui.radio_list.currentRow())) self.playListMohaveMusic.setCurrentIndex( self.random.bounded(0, 9) + 1) self.playlisNewVegas.setCurrentIndex( self.random.bounded(0, 10) + 1) self.player.play() self.play = True return True else: #print(event.key()) return True return super(MainWindow, self).eventFilter(obj, event) @Slot() def shift(self): print(self.ui.stat_tab.currentIndex()) index = self.ui.stat_tab.currentIndex() if index == 0: self.ui.stat_tab.setGeometry(0, 0, 904, 380) elif index == 1: self.ui.stat_tab.setGeometry(-108, 0, 904, 380) elif index == 2: self.ui.stat_tab.setGeometry(-214, 0, 904, 380)
class Board(QMainWindow, board_funcs): """ Description ------------- The board for Trivial Purfuit. TODO: JGC - Merge the common stuff between board_funcs and this class. There's duplicate code, but you did everything in this class first. """ def __init__(self): super().__init__() self.setWindowTitle("Trivial Purfuit Board") self.num_row_tiles = 9 self.num_col_tiles = 9 self.board_tile_width = 95 self.board_tile_height = self.board_tile_width self.board_width = self.num_row_tiles * self.board_tile_width self.board_height = self.num_col_tiles * self.board_tile_height monitor = QApplication.desktop().geometry() self.resize(monitor.width(), self.board_height) #default is event self.qtype1_tile_color = Qt.white #default is holidau self.qtype2_tile_color = Qt.green #default is location self.qtype3_tile_color = Qt.blue #default is people self.qtype4_tile_color = Qt.red self.roll_again_tile_color = Qt.darkGray self.players_initialized = False self.dice_initialized = False # Background music playlist self.playlist = QMediaPlaylist() self.playlist.addMedia( QUrl.fromLocalFile( definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/sea_change.mp3")) self.playlist.addMedia( QUrl.fromLocalFile(definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/feblu.mp3")) self.playlist.addMedia( QUrl.fromLocalFile( definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/vals_de_rodrigues.mp3")) self.playlist.addMedia( QUrl.fromLocalFile( definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/escaping_time.mp3")) self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.playlist_player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.playlist_player.setPlaylist(self.playlist) self.number_of_players = 0 self.player_list = [] self.die = Die() self.board_menu = BoardMenu() self.qa_manager = QuestionManager( definitions.ROOT_DIR + "/Trivial_Purfuit/csvs/questions-and-answers.csv") self.question_categories = [ definitions.question_type1, definitions.question_type2, definitions.question_type3, definitions.question_type4 ] self.image_path = definitions.ROOT_DIR + "/Trivial_Purfuit/src/board/images/" self.restart_menu = RestartMenu() # end __init__() def initialize_game(self): """ Description ------------- - TODO: JGC """ monitor = QApplication.desktop().geometry() # Navigation Menu setup self.board_menu.resize(monitor.width(), monitor.height()) self.board_menu.ui.player_order_group_box.move( self.board_width, self.board_menu.ui.player_order_group_box.y()) self.board_menu.ui.navigation_group.move(self.board_width, monitor.height() / 3) temp_x = self.board_menu.ui.navigation_group.x() temp_y = self.board_menu.ui.navigation_group.y( ) + self.board_menu.ui.navigation_group.height() self.board_menu.ui.misc_group.move(temp_x, temp_y) self.board_menu.ui.audio_group.move( self.board_menu.ui.misc_group.x(), self.board_menu.ui.misc_group.y() + self.board_menu.ui.misc_group.height()) # Connect signals/slots for buttons on board menu self.connect(self.board_menu.ui.up_button, SIGNAL("clicked()"), partial(self.start_move, "UP")) self.connect(self.board_menu.ui.down_button, SIGNAL("clicked()"), partial(self.start_move, "DOWN")) self.connect(self.board_menu.ui.left_button, SIGNAL("clicked()"), partial(self.start_move, "LEFT")) self.connect(self.board_menu.ui.right_button, SIGNAL("clicked()"), partial(self.start_move, "RIGHT")) self.connect(self.board_menu.ui.reset_button, SIGNAL("clicked()"), self.cheat) self.connect(self.board_menu.ui.roll_die_button, SIGNAL("clicked()"), self.get_dice_value) # Connect signals/slots for audio slider widgets on board menu self.connect(self.board_menu.ui.music_volume_slider, SIGNAL("sliderReleased()"), self.update_music_volume) self.connect(self.board_menu.ui.sound_effects_volume, SIGNAL("sliderReleased()"), self.update_sound_effect_volume) self.board_menu.ui.sound_effects_volume.setValue(50) self.board_menu.ui.music_volume_slider.setValue(50) # Die Setup/initialization self.initialize_dice() # Game sounds self.win_noise = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.lose_noise = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.win_noise.setMedia( QUrl.fromLocalFile( definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/win_bing.mp3")) self.lose_noise.setMedia( QUrl.fromLocalFile( definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/lose_noise.mp3")) # Start the background music self.playlist_player.play() self.layout().addChildWidget(self.die) self.layout().addChildWidget(self.board_menu) self.player_list = self.set_round_order(self.player_list) self.current_player = self.player_list[0] self.current_player_list_index = 0 self.current_player.is_current_player = True self.board_menu.ui.current_player_field.insertPlainText( str(self.current_player.name)) # end initialize_game() def hide_dirs(self): self.board_menu.ui.down_button.setVisible(False) self.board_menu.ui.up_button.setVisible(False) self.board_menu.ui.left_button.setVisible(False) self.board_menu.ui.right_button.setVisible(False) #end hide_dirs def avail_dirs(self): """ Determines possible directions the player could move based on current location Input: The player token who is currently moving Output: List of available directions """ player_row = self.current_player.location[0] player_col = self.current_player.location[1] directions = list() if self.get_tile_type(player_row + 1, player_col) != "Invalid": directions.append("Down") if self.get_tile_type(player_row - 1, player_col) != "Invalid": directions.append("Up") if self.get_tile_type(player_row, player_col - 1) != "Invalid": directions.append("Left") if self.get_tile_type(player_row, player_col + 1) != "Invalid": directions.append("Right") return directions def update_dirs(self): """ Hides the movement buttons based on whether or not its a valid move Input: Output: """ player_row = self.current_player.location[0] player_col = self.current_player.location[1] self.board_menu.ui.down_button.setVisible(True) self.board_menu.ui.up_button.setVisible(True) self.board_menu.ui.left_button.setVisible(True) self.board_menu.ui.right_button.setVisible(True) if self.get_tile_type(player_row + 1, player_col) == "Invalid" \ or self.current_player.direction_to_move == "UP": self.board_menu.ui.down_button.setVisible(False) if self.get_tile_type(player_row - 1, player_col) == "Invalid" \ or self.current_player.direction_to_move == "DOWN": self.board_menu.ui.up_button.setVisible(False) if self.get_tile_type(player_row, player_col - 1) == "Invalid" \ or self.current_player.direction_to_move == "RIGHT": self.board_menu.ui.left_button.setVisible(False) if self.get_tile_type(player_row, player_col + 1) == "Invalid" \ or self.current_player.direction_to_move == "LEFT": self.board_menu.ui.right_button.setVisible(False) # end update_dirs() def set_default_game_volume(self): self.playlist_player.setVolume(50) self.board_menu.ui.music_volume_slider.setValue(50) self.board_menu.ui.music_volume_slider.setValue(50) # end set_default_game_volume def update_music_volume(self): tmp_volume = self.board_menu.ui.music_volume_slider.value() self.playlist_player.setVolume(tmp_volume) # end update_music_volume() def update_sound_effect_volume(self): tmp_volume = self.board_menu.ui.sound_effects_volume.value() # Set volume for lose/win effects self.win_noise.setVolume(tmp_volume) self.lose_noise.setVolume(tmp_volume) # Set the volume for each player token for player in self.player_list: player.audio_player.setVolume(tmp_volume) # Set the die volume self.die.audio_player.setVolume(tmp_volume) # end update_sound_effect_volume() def get_dice_value(self): """ Description ------------- - TODO: JGC """ self.current_player.moves_left = self.die.roll() self.current_player.direction_to_move = "NONE" self.board_menu.ui.dice_field.clear() self.board_menu.ui.dice_field.insertPlainText( str(self.current_player.moves_left)) self.board_menu.ui.current_player_field.clear() self.board_menu.ui.current_player_field.insertPlainText( str(self.current_player.name)) self.update_dirs() self.board_menu.ui.roll_die_button.setVisible(False) if self.current_player.moves_left == 6: self.current_player.moves_left = 0 self.hide_dirs() self.board_menu.ui.roll_die_button.setVisible(True) answer, valid_input = QInputDialog().getItem( self, "Select Cake Headquarters", "Select:", self.question_categories, 0, False) if answer == self.question_categories[0]: self.current_player.location[0] = 4 self.current_player.location[1] = 8 self.current_player.x = self.board_tile_width * 9 - ( self.current_player.width * self.current_player.x_offset) self.current_player.y = self.board_tile_height * 5 - ( self.current_player.height * self.current_player.y_offset) elif answer == self.question_categories[1]: self.current_player.location[0] = 8 self.current_player.location[1] = 4 self.current_player.x = self.board_tile_width * 5 - ( self.current_player.width * self.current_player.x_offset) self.current_player.y = self.board_tile_height * 9 - ( self.current_player.height * self.current_player.y_offset) elif answer == self.question_categories[2]: self.current_player.location[0] = 0 self.current_player.location[1] = 4 self.current_player.x = self.board_tile_width * 5 - ( self.current_player.width * self.current_player.x_offset) self.current_player.y = self.board_tile_height * 1 - ( self.current_player.height * self.current_player.y_offset) elif answer == self.question_categories[3]: self.current_player.location[0] = 4 self.current_player.location[1] = 0 self.current_player.x = self.board_tile_width * 1 - ( self.current_player.width * self.current_player.x_offset) self.current_player.y = self.board_tile_height * 5 - ( self.current_player.height * self.current_player.y_offset) else: print("Incorrect answer") self.current_player.turn_status = True self.current_player.draw_token = True self.current_player.update() self.perform_tile_action() self.board_menu.ui.dice_field.clear() # Updates the dice image to immediately reflect the correct image. self.die.update() # end get_dice_value() def start_move(self, label): """ Description ------------- - TODO: JGC """ try: # TODO: Could add a check to restart for those too impatient. self.current_player.audio_player.play() if (label == "UP" or label == "DOWN" or label == "LEFT" or label == "RIGHT"): while (self.current_player.moves_left > 0): self.current_player.direction_to_move = label self.current_player.turn_status = True self.current_player.update_location(direction=label) self.update_dirs() self.current_player.moves_left = self.current_player.moves_left - 1 self.board_menu.ui.dice_field.clear() self.board_menu.ui.dice_field.insertPlainText( str(self.current_player.moves_left)) if len(self.avail_dirs() ) > 2 and self.current_player.moves_left != 0: break else: if self.current_player.location == [0, 0]: if self.current_player.direction_to_move == "UP": label = "RIGHT" else: label = "DOWN" elif self.current_player.location == [0, 8]: if self.current_player.direction_to_move == "UP": label = "LEFT" else: label = "DOWN" elif self.current_player.location == [8, 0]: if self.current_player.direction_to_move == "DOWN": label = "RIGHT" else: label = "UP" elif self.current_player.location == [8, 8]: if self.current_player.direction_to_move == "DOWN": label = "LEFT" else: label = "UP" if self.current_player.moves_left == 0: self.current_player.done_moving = True # end if # Manually calls the paint QEvent. self.update() # Once the player is out of spaces to move, prompt the player with a # question from the QA Manager. if self.current_player.moves_left == 0 and self.current_player.done_moving: self.current_player.direction_to_move = "NONE" self.hide_dirs() self.board_menu.ui.roll_die_button.setVisible(True) self.current_player.done_moving = False self.perform_tile_action() # end if else: print("No moves left!") except ValueError: print("[ERROR] Invalid dice roll amount!") # end start_move() def initialize_player_tokens(self, total_players, player_one, player_two, player_three, player_four): """ Description ------------- TODO: JGC - """ if total_players >= 1: self.player_widget = PlayerToken(player_one, self.board_tile_width, self.board_tile_height, 2.6, 2.6) self.player_widget.resize(self.board_width, self.board_height) self.layout().addChildWidget(self.player_widget) self.player_list.append(self.player_widget) if total_players >= 2: player_widget_two = PlayerToken(player_two, self.board_tile_width, self.board_tile_height, 1, 1) player_widget_two.resize(self.board_width, self.board_height) self.layout().addChildWidget(player_widget_two) self.player_list.append(player_widget_two) if total_players >= 3: player_widget_three = PlayerToken(player_three, self.board_tile_width, self.board_tile_height, 2.6, 1) player_widget_three.resize(self.board_width, self.board_height) self.layout().addChildWidget(player_widget_three) self.player_list.append(player_widget_three) if total_players >= 4: player_widget_four = PlayerToken(player_four, self.board_tile_width, self.board_tile_height, 1, 2.6) player_widget_four.resize(self.board_width, self.board_height) self.layout().addChildWidget(player_widget_four) self.player_list.append(player_widget_four) # end initialize_player_tokens() def initialize_dice(self): """ Description ------------- - TODO: JGC """ self.die.board_tile_height = self.board_tile_height self.die.board_tile_width = self.board_tile_width self.die.resize(self.board_width, self.board_height) # end initialize_dice() def cheat(self): """ Description ------------- - TODO: JGC """ self.current_player.award_cake_piece(self.question_categories[0]) self.current_player.award_cake_piece(self.question_categories[1]) self.current_player.award_cake_piece(self.question_categories[2]) self.current_player.award_cake_piece(self.question_categories[3]) self.current_player.update() # end reset_player() def is_roll_again_tile(self, row, col): """ Description ------------- Checks if the current row and column position is a holiday tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if ((row == 0 and col == 0) or (row == 0 and col == 8) or (row == 8 and col == 0) or (row == 8 and col == 8)): return True # end if # end is_roll_again_tile() def is_qtype1_tile(self, row, col): """ Description ------------- Checks if the current row and column position is a person tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if ((row == 0 and col == 3) or (row == 0 and col == 6) or (row == 1 and col == 0) or (row == 3 and col == 4) or (row == 4 and col == 2) or (row == 4 and col == 8) or (row == 5 and col == 0) or (row == 7 and col == 4) or (row == 8 and col == 1) or (row == 8 and col == 7)): return True # end if # end is_person_tile() def is_qtype2_tile(self, row, col): """ Description ------------- Checks if the current row and column position is an event tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if ((row == 0 and col == 2) or (row == 0 and col == 5) or (row == 2 and col == 0) or (row == 2 and col == 4) or (row == 3 and col == 8) or (row == 4 and col == 1) or (row == 4 and col == 5) or (row == 7 and col == 0) or (row == 7 and col == 8) or (row == 8 and col == 4)): return True # end if # end is_event_tile() def is_qtype3_tile(self, row, col): """ Description ------------- Checks if the current row and column position is a location/place tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if ((row == 0 and col == 4) or (row == 1 and col == 8) or (row == 3 and col == 0) or (row == 4 and col == 3) or (row == 4 and col == 7) or (row == 6 and col == 0) or (row == 6 and col == 4) or (row == 6 and col == 8) or (row == 8 and col == 2) or (row == 8 and col == 5)): return True # end if # end is_place_tile() def is_qtype4_tile(self, row, col): """ Description ------------- Checks if the current row and column position is a holiday tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if ((row == 0 and col == 1) or (row == 0 and col == 7) or (row == 1 and col == 4) or (row == 2 and col == 8) or (row == 4 and col == 0) or (row == 4 and col == 6) or (row == 5 and col == 4) or (row == 5 and col == 8) or (row == 8 and col == 3) or (row == 8 and col == 6)): return True # end if # end is_holiday_tile() def is_hub_tile(self, row, col): """ Description ------------- Checks if the current row and column position is the hub tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if (row == 4 and col == 4): return True # end is_hub_tile() def is_cake_tile(self, row, col): """ Description ------------- Checks if the current row and column position is a cake tile. Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if ((row == 0 and col == 4) or (row == 4 and col == 0) or (row == 4 and col == 8) or (row == 8 and col == 4)): return True # end is_cake_tile() def get_tile_type(self, row, col): """ Description ------------- Utilizes previous methods for tile checking to return a string of what tile type the current row and column position is Parameters ------------- (1) row: The selected row on the board. (2) col: The selected column on the board. """ if self.is_hub_tile(row, col): return "hub" elif self.is_qtype1_tile(row, col): return self.question_categories[0] elif self.is_qtype2_tile(row, col): return self.question_categories[1] elif self.is_qtype3_tile(row, col): return self.question_categories[2] elif self.is_qtype4_tile(row, col): return self.question_categories[3] elif self.is_roll_again_tile(row, col): return "roll_again" else: return "Invalid" # end get_tile_type() def paintEvent(self, event): """ Description ------------- - Draws the board and player tokens Parameters ------------- (1) event: The event signal (QEvent.Type.Paint). """ self.draw_board() if not self.dice_initialized: self.die.update() self.dice_initialized = True # end if for player in self.player_list: self.do_player_turn(player) # end paintEvent() def do_player_turn(self, player): """ Description ------------- TODO: JGC """ if player.turn_status: player.draw_token = True player.update() player.turn_status = False # end if # end do_player_turn() def perform_tile_action(self): """ Description ------------- - TODO: JGC """ self.current_player.update() tile_type = self.get_tile_type(self.current_player.location[0], self.current_player.location[1]) roll_again = False if tile_type in self.question_categories: good_answer = self.ask_question(self.current_player, tile_type, isCake=False) if good_answer: self.win_noise.play() roll_again = True # Verify this is a "Cake" Tile before awarding cake piece. if self.is_cake_tile(self.current_player.location[0], self.current_player.location[1]): self.current_player.award_cake_piece( cake_category=tile_type) else: self.lose_noise.play() elif (tile_type == "roll_again"): self.win_noise.play() roll_again = True QMessageBox.question(self, 'Congratulations!', 'Roll Again!', QMessageBox.Ok) elif (tile_type == "hub"): # Verify the player token has all cake pieces awarded before answering the # winning question, otherwise ask random question if self.current_player.all_cake_pieces_present(): answer, valid_input = QInputDialog().getItem( self, "Select Category", "!OTHER PLAYERS! Select the winning question category:", self.question_categories, 0, False) good_answer = self.ask_question(self.current_player, answer, isCake=False) if good_answer: self.win_noise.play() QMessageBox.question(self, 'Congratulations!', 'YOU WIN!', QMessageBox.Ok) self.restart_menu.show() else: self.lose_noise.play() else: answer, valid_input = QInputDialog().getItem( self, "Select Category", "Select the question category:", self.question_categories, 0, False) good_answer = self.ask_question(self.current_player, answer, isCake=False) if good_answer: roll_again = True else: self.lose_noise.play() else: print("Invalid Tile/Question Type Received") print("Row: " + str(self.current_player.location[0])) print("Col: " + str(self.current_player.location[1])) # If not roll again tile, point to the next player in the list if not roll_again: # Deactivate the yellow outline for current player self.current_player.is_current_player = False self.current_player_list_index = (self.current_player_list_index + 1) % len(self.player_list) self.current_player = self.player_list[ self.current_player_list_index] self.current_player.is_current_player = True self.board_menu.ui.current_player_field.clear() self.board_menu.ui.current_player_field.insertPlainText( str(self.current_player.name)) self.board_menu.ui.dice_field.clear() # end if # end perform_tile_action def draw_board(self): """ Description ------------- - Paint all of the tiles for the Trivial Purfuit board Parameters ------------- (1) event: The event signal (QEvent.Type.Paint). NOTE/TODO ------------- (1) Don't be lazy and brute force.. (2) Run the current board layout by the team """ painter = QPainter(self) painter.setPen(QPen(Qt.black, 5, Qt.SolidLine)) x = 0 y = 0 # The board is drawn from left to right. for row in range(self.num_row_tiles): for col in range(self.num_col_tiles): if self.is_roll_again_tile(row, col): painter.setBrush( QBrush(self.roll_again_tile_color, Qt.SolidPattern)) painter.drawRect(x, y, self.board_tile_width, self.board_tile_height) painter.drawImage( QRect(x, y, self.board_tile_width, self.board_tile_height), QImage(self.image_path + "roll_again.png")) elif self.is_qtype1_tile(row, col): painter.setBrush( QBrush(self.qtype1_tile_color, Qt.SolidPattern)) painter.drawRect(x, y, self.board_tile_width, self.board_tile_height) if self.is_cake_tile(row, col): painter.drawImage( QRect(x, y, self.board_tile_width, self.board_tile_height), QImage(self.image_path + "collect.png")) elif self.is_qtype4_tile(row, col): painter.setBrush( QBrush(self.qtype4_tile_color, Qt.SolidPattern)) painter.drawRect(x, y, self.board_tile_width, self.board_tile_height) if self.is_cake_tile(row, col): painter.drawImage( QRect(x, y, self.board_tile_width, self.board_tile_height), QImage(self.image_path + "collect.png")) elif self.is_qtype2_tile(row, col): painter.setBrush( QBrush(self.qtype2_tile_color, Qt.SolidPattern)) painter.drawRect(x, y, self.board_tile_width, self.board_tile_height) if self.is_cake_tile(row, col): painter.drawImage( QRect(x, y, self.board_tile_width, self.board_tile_height), QImage(self.image_path + "collect.png")) elif self.is_qtype3_tile(row, col): painter.setBrush( QBrush(self.qtype3_tile_color, Qt.SolidPattern)) painter.drawRect(x, y, self.board_tile_width, self.board_tile_height) if self.is_cake_tile(row, col): painter.drawImage( QRect(x, y, self.board_tile_width, self.board_tile_height), QImage(self.image_path + "collect.png")) elif self.is_hub_tile(row, col): painter.drawImage( QRect(x, y, self.board_tile_width, self.board_tile_height), QImage(self.image_path + "win.png")) # Quadrant One elif row == 1 and col == 1: painter.drawImage( QRect(self.board_tile_width, self.board_tile_height, self.board_tile_width * 3, self.board_tile_height * 3), QImage(self.image_path + "american_flag.jpeg")) # Quadrant Two elif row == 5 and col == 1: painter.drawImage( QRect(self.board_tile_width * row, self.board_tile_height, self.board_tile_width * 3, self.board_tile_height * 3), QImage(self.image_path + "fireworks-two.jpg")) # Quadrant Three elif row == 1 and col == 5: painter.drawImage( QRect(self.board_tile_width, self.board_tile_height * col, self.board_tile_width * 3, self.board_tile_height * 3), QImage(self.image_path + "underwear_guy.jpeg")) # Quadrant Four elif row == 5 and col == 5: painter.drawImage( QRect(self.board_tile_width * row, self.board_tile_height * col, self.board_tile_width * 3, self.board_tile_height * 3), QImage(self.image_path + "doi.jpg")) # end if # Update to x-coordinate for next tile x = x + self.board_tile_width # end for # Reset (x,y) starting coordinates for next row and columns y = y + self.board_tile_height x = 0 # end for self.board_initialized = True
class MainWindow(QObject): #class constructor def __init__(self, ui_file, parent=None): #reference to our music player self.music_player = QMediaPlayer() self.music_player.setVolume(50) #call parent QObject constructor super(MainWindow, self).__init__(parent) #load the UI file into Python ui_file = QFile(ui_file) ui_file.open(QFile.ReadOnly) loader = QUiLoader() self.window = loader.load(ui_file) #always remember to close files ui_file.close() #add playlist object self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.music_player.setPlaylist(self.playlist) self.music_player.setNotifyInterval(50) #add a listener to change audio filename displayed #add playlist display object self.playlistDisplay = self.window.findChild(QListWidget, 'PlayListWidget') #self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemOnce) #self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) #self.playlist.setPlaybackMode(QMediaPlaylist.Random) #self.playlist.setPlaybackMode(QMediaPlaylist.Loop) #add event listeners self.add_media_action = self.window.findChild(QAction, 'action_add_media') self.add_media_action.triggered.connect(self.add_media_triggered) self.quit_action = self.window.findChild(QAction, 'action_quit') self.quit_action.triggered.connect(self.quit_action_triggered) self.NextButton = self.window.findChild(QPushButton, 'NextButton') self.NextButton.clicked.connect(self.next_button_clicked) self.PauseButton = self.window.findChild(QPushButton, 'PauseButton') self.PauseButton.clicked.connect(self.pause_button_clicked) #PlayAllRadioButton = self.window.findChild(QRadioButton, 'PlayAllRadioButton') #PlayAllRadioButton.clicked.connect(self.play_all_button_clicked) self.PlayButton = self.window.findChild(QPushButton, 'PlayButton') self.PlayButton.clicked.connect(self.play_button_clicked) self.PreviousButton = self.window.findChild(QPushButton, 'PreviousButton') self.PreviousButton.clicked.connect(self.previous_button_clicked) #ProgressBar = self.window.findChild(QProgressBar, 'ProgressBar') #ProgressBar.valueChanged.connect(self.progress_bar_moved) self.RepeatOnceRadioButton = self.window.findChild( QRadioButton, 'RepeatOnceRadioButton') self.RepeatOnceRadioButton.clicked.connect( self.repeat_once_button_clicked) self.RepeatRadioButton = self.window.findChild(QRadioButton, 'RepeatRadioButton') self.RepeatRadioButton.clicked.connect(self.repeat_button_clicked) #ShuffleCheckBox = self.window.findChild(QCheckBox, 'ShuffleCheckBox') #ShuffleCheckBox.clicked.connect(self.shuffle_checkbox_clicked) #ShuttleSlider = self.window.findChild(QSlider, 'ShuttleSlider') #ShuttleSlider.valueChanged.connect(self.shuttle_slider_moved) self.VolumeSlider = self.window.findChild(QSlider, 'VolumeSlider') self.VolumeSlider.setValue(50) self.VolumeSlider.valueChanged.connect(self.change_volume_level) self.ProgressBar = self.window.findChild(QProgressBar, 'ProgressBar') self.music_player.durationChanged.connect( self.progress_bar_maximum_changed) self.music_player.positionChanged.connect( self.progress_bar_position_changed) #self.Playlist = self.window.findChild(QMediaPlaylist, 'Playlist') #self.Playlist.itemDoubleClicked.connect(self.volume_slider_moved) #show window to user self.window.show() #I referenced code from Jordan Abbott to complete this function def add_media_triggered(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames(None, "Select Media Files", "", "All Files (*)", options=options) if files: for file in files: self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(file))) self.playlistDisplay.addItem(os.path.basename(file)) def quit_action_triggered(self): self.window.close() def pause_button_clicked(self): self.music_player.pause() def next_button_clicked(self): if self.music_player.currentMedia().isNull(): self.playlist.setCurrentIndex(1) self.music_player.play() else: self.playlist.next() #def play_all_button_clicked(self): # def play_button_clicked(self): if self.music_player.currentMedia().isNull(): self.playlist.setCurrentIndex(1) self.next_button_clicked() self.music_player.play() else: self.music_player.play() print(QMediaPlayer.EndOfMedia) def previous_button_clicked(self): self.playlist.previous() def progress_bar_maximum_changed(self, maximum): self.ProgressBar.setMaximum(maximum) # = self.music_player.duration() #def durationChanged(self, duration): # self.positionSlider.setRange(0, duration) def progress_bar_position_changed(self, position): self.ProgressBar.setValue(position) def repeat_once_button_clicked(self, status): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemOnce) self.play_button_clicked() self.RepeatOnceRadioButton.setAutoExclusive(False) self.RepeatOnceRadioButton.setChecked(False) self.RepeatOnceRadioButton.setAutoExclusive(True) def repeat_button_clicked(self): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemLoop) #def shuffle_checkbox_clicked(self): #add code #def shuttle_slider_moved(self): #add code def change_volume_level(self): self.music_player.setVolume(self.VolumeSlider.value())
class Channel(QObject): def __init__(self, name: T.Optional[str], parent: T.Optional[QObject] = None) -> None: super().__init__(parent) self.name = name self.slider_volume: Number = 100 self.threshold = PlaybackThreshold.Everything self._loop_sound: T.Optional[Sound] = None self._loop_player = QMediaPlayer(self) self._loop_volume_adjustment: Number = 0 self._loop_player.setAudioRole(QAudio.GameRole) self._loop_playlist = QMediaPlaylist(self) self._loop_playlist.setPlaybackMode(QMediaPlaylist.CurrentItemOnce) self._loop_player.setPlaylist(self._loop_playlist) self._loop_player.stateChanged.connect( self._on_loop_player_state_changed) self._one_shot_player = QMediaPlayer(self) self._one_shot_volume_adjustment: Number = 0 self._one_shot_player.setAudioRole(QAudio.GameRole) self._one_shot_player.stateChanged.connect( self._on_one_shot_player_state_changed) @property def is_playing(self): return (self._loop_player.state() == QMediaPlayer.PlayingState or self._one_shot_player.state() == QMediaPlayer.PlayingState) def _on_loop_player_state_changed(self, state: QMediaPlayer.State) -> None: logger.trace("Loop player state changed: {!r}", state) if state != QMediaPlayer.StoppedState: return decibel = -self._loop_volume_adjustment logger.trace("Readjusting loop player volume by {}db", decibel) self.adjust_player_volume_by_decibel(self._loop_player, decibel) self._loop_volume_adjustment = 0 # Loop playlist is empty if not self._loop_playlist.mediaCount(): logger.trace("Loop playlist is empty, not queueing a new file") return # This shouldn't ever happen, it's just here to make mypy happy if not self._loop_sound: return file = random.choices(self._loop_sound.files, [file.weight for file in self._loop_sound.files])[0] index = self._loop_sound.files.index(file) logger.trace( "Loop player playing file: {!r} at playlist index: {}", file, index, ) self._loop_playlist.setCurrentIndex(index) self._loop_player.play() def _on_one_shot_player_state_changed(self, state: QMediaPlayer.State) -> None: logger.trace("One-shot player state changed: {!r}", state) if state != QMediaPlayer.StoppedState: return decibel = -self._one_shot_volume_adjustment logger.trace("Readjusting one-shot player volume by {}db", decibel) self.adjust_player_volume_by_decibel(self._one_shot_player, decibel) self._one_shot_volume_adjustment = 0 logger.trace("One-shot player stopped, resuming loop player") self._loop_player.play() def play_sound(self, sound: Sound) -> None: if sound.playback_threshold > self.threshold: logger.trace("Ignoring sound {!r} because of threshold", sound) return if sound.loop is Loop.Start: self._loop_sound = sound # New looping sound, rebuild playlist self._loop_playlist.clear() for file in sound.files: media = QUrl.fromLocalFile(file.file_name) self._loop_playlist.addMedia(media) # Select file based on weight and set the matching playlist index weights = [file.weight for file in sound.files] file = random.choices(sound.files, weights)[0] index = sound.files.index(file) self._loop_playlist.setCurrentIndex(index) logger.trace("Adjusting loop player volume by {}db", file.volume_adjustment) self._loop_volume_adjustment = self.adjust_player_volume_by_decibel( self._loop_player, file.volume_adjustment) logger.trace("Adjusted One-shot player volume by {}db", self._loop_volume_adjustment) self._loop_player.play() logger.trace( "Loop player playing file: {!r} at playlist index: {}", file, index, ) return if sound.loop is Loop.Stop: logger.trace("Stopping loop player") self._loop_sound = None self._loop_playlist.clear() self._loop_player.stop() else: logger.trace("Pausing loop player for one-shot sound") self._loop_player.pause() file = random.choices(sound.files, [file.weight for file in sound.files])[0] media = QUrl.fromLocalFile(file.file_name) self._one_shot_player.setMedia(media) self._one_shot_volume_adjustment = self.adjust_player_volume_by_decibel( self._one_shot_player, file.volume_adjustment) logger.trace("Adjusted one-shot player volume by {}db", self._one_shot_volume_adjustment) self._one_shot_player.play() logger.trace("One-shot player playing file: {!r}", file) def set_player_volumes(self, volume: Number) -> None: volume = round(volume) self._loop_player.setVolume(volume) self._one_shot_player.setVolume(volume) # noinspection PyMethodMayBeStatic def adjust_player_volume_by_decibel(self, player: QMediaPlayer, decibel: Number) -> Number: original_volume = player.volume() target_volume = round( add_decibel_to_linear_volume(original_volume, decibel)) player.setVolume(target_volume) # Return clamped volume difference, so increasing linear volume 100 by n > 1 db # returns 0 return player.volume() - original_volume def set_threshold(self, threshold: PlaybackThreshold) -> None: logger.trace("Setting channel threshold: {!r}", threshold) self.threshold = threshold if not self._loop_sound: return if self._loop_sound.playback_threshold > threshold: logger.trace("Stopping loop player, new threshold too low") self._loop_playlist.clear() self._loop_player.stop() return logger.trace("Loop player state: {!r}", self._loop_player.state()) if (self._loop_sound.playback_threshold <= threshold and self._loop_player.state() == QMediaPlayer.StoppedState): logger.trace( "Replaying sound: {!r} in loop player from stopped state") self.play_sound(self._loop_sound)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.playlist = QMediaPlaylist() self.player = QMediaPlayer() toolBar = QToolBar() self.addToolBar(toolBar) fileMenu = self.menuBar().addMenu("&File") openAction = QAction(QIcon.fromTheme("document-open"), "&Open...", self, shortcut=QKeySequence.Open, triggered=self.open) fileMenu.addAction(openAction) exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit", self, shortcut="Ctrl+Q", triggered=self.close) fileMenu.addAction(exitAction) playMenu = self.menuBar().addMenu("&Play") playIcon = self.style().standardIcon(QStyle.SP_MediaPlay) self.playAction = toolBar.addAction(playIcon, "Play") self.playAction.triggered.connect(self.player.play) playMenu.addAction(self.playAction) previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward) self.previousAction = toolBar.addAction(previousIcon, "Previous") self.previousAction.triggered.connect(self.previousClicked) playMenu.addAction(self.previousAction) pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause) self.pauseAction = toolBar.addAction(pauseIcon, "Pause") self.pauseAction.triggered.connect(self.player.pause) playMenu.addAction(self.pauseAction) nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward) self.nextAction = toolBar.addAction(nextIcon, "Next") self.nextAction.triggered.connect(self.playlist.next) playMenu.addAction(self.nextAction) stopIcon = self.style().standardIcon(QStyle.SP_MediaStop) self.stopAction = toolBar.addAction(stopIcon, "Stop") self.stopAction.triggered.connect(self.player.stop) playMenu.addAction(self.stopAction) self.volumeSlider = QSlider() self.volumeSlider.setOrientation(Qt.Horizontal) self.volumeSlider.setMinimum(0) self.volumeSlider.setMaximum(100) self.volumeSlider.setFixedWidth(app.desktop().availableGeometry(self).width() / 10) self.volumeSlider.setValue(self.player.volume()) self.volumeSlider.setTickInterval(10) self.volumeSlider.setTickPosition(QSlider.TicksBelow) self.volumeSlider.setToolTip("Volume") self.volumeSlider.valueChanged.connect(self.player.setVolume) toolBar.addWidget(self.volumeSlider) aboutMenu = self.menuBar().addMenu("&About") aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt) aboutMenu.addAction(aboutQtAct) self.videoWidget = QVideoWidget() self.setCentralWidget(self.videoWidget) self.player.setPlaylist(self.playlist) self.player.stateChanged.connect(self.updateButtons) self.player.setVideoOutput(self.videoWidget) self.updateButtons(self.player.state()) def open(self): fileDialog = QFileDialog(self) supportedMimeTypes = QMediaPlayer.supportedMimeTypes() if not supportedMimeTypes: supportedMimeTypes.append("video/x-msvideo") # AVI fileDialog.setMimeTypeFilters(supportedMimeTypes) moviesLocation = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation) fileDialog.setDirectory(moviesLocation) if fileDialog.exec_() == QDialog.Accepted: self.playlist.addMedia(fileDialog.selectedUrls()[0]) self.player.play() def previousClicked(self): # Go to previous track if we are within the first 5 seconds of playback # Otherwise, seek to the beginning. if self.player.position() <= 5000: self.playlist.previous() else: player.setPosition(0) def updateButtons(self, state): mediaCount = self.playlist.mediaCount() self.playAction.setEnabled(mediaCount > 0 and state != QMediaPlayer.PlayingState) self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState) self.stopAction.setEnabled(state != QMediaPlayer.StoppedState) self.previousAction.setEnabled(self.player.position() > 0) self.nextAction.setEnabled(mediaCount > 1)
class MainWindow(QObject): #class constructor def __init__(self, ui_file, parent=None): #reference to our music player self.music_player = QMediaPlayer() self.music_playlist = QMediaPlaylist() self.music_player.setVolume(80) #call parent QObject constructor super(MainWindow, self).__init__(parent) #load the UI file into Python ui_file = QFile(ui_file) ui_file.open(QFile.ReadOnly) loader = QUiLoader() self.window = loader.load(ui_file) self.window.setWindowFlags(Qt.MSWindowsFixedSizeDialogHint) self.window.setWindowTitle("SynthWAV") #always remember to close files ui_file.close() #add event listeners open_action = self.window.findChild(QAction, 'action_open') open_action.triggered.connect(self.open_action_triggered) quit_action = self.window.findChild(QAction, 'action_quit') quit_action.triggered.connect(self.quit_action_triggered) open_button = self.window.findChild(QPushButton, 'open_button') open_button.clicked.connect(self.open_action_triggered) quit_button = self.window.findChild(QPushButton, 'quit_button') quit_button.clicked.connect(self.quit_action_triggered) play_button = self.window.findChild(QPushButton, 'play_button') play_button.clicked.connect(self.play_button_clicked) pause_button = self.window.findChild(QPushButton, 'pause_button') pause_button.clicked.connect(self.pause_button_clicked) stop_button = self.window.findChild(QPushButton, 'stop_button') stop_button.clicked.connect(self.stop_button_clicked) progress_slider = self.window.findChild(QSlider, 'progress_slider') self.music_player.positionChanged.connect(self.update_progress) progress_slider.sliderMoved.connect(self.scrub_progress) volume_slider = self.window.findChild(QSlider, 'volume_slider') volume_slider.setValue(self.music_player.volume()) volume_slider.sliderMoved.connect(self.adjust_volume) next_button = self.window.findChild(QPushButton, 'next_button') next_button.clicked.connect(self.next_button_clicked) previous_button = self.window.findChild(QPushButton, 'previous_button') previous_button.clicked.connect(self.previous_button_clicked) fforward_button = self.window.findChild(QPushButton, 'fforward_button') fforward_button.clicked.connect(self.fforward_button_clicked) fbackward_button = self.window.findChild(QPushButton, 'fbackward_button') fbackward_button.clicked.connect(self.fbackward_button_clicked) self.music_playlist.currentMediaChanged.connect(self.change_title) #show window to user self.window.show() def open_action_triggered(self): files = QFileDialog.getOpenFileNames(self.window, "Add songs to playlist") for i in range(len(files[0])): self.music_playlist.addMedia(QUrl.fromLocalFile(str(files[0][i]))) self.music_playlist.setCurrentIndex(0) self.music_player.setPlaylist(self.music_playlist) def change_title(self): title_label = self.window.findChild(QLabel, 'media_title') show_title_path = self.music_playlist.currentMedia().canonicalUrl( ).fileName() show_title = os.path.splitext(show_title_path) title_label.setText(show_title[0]) def quit_action_triggered(self): self.window.close() def play_button_clicked(self): self.music_player.play() def pause_button_clicked(self): self.music_player.pause() def stop_button_clicked(self): self.music_player.stop() def next_button_clicked(self): self.music_playlist.next() def previous_button_clicked(self): self.music_playlist.previous() def fforward_button_clicked(self): self.music_player.setPosition(self.music_player.position() + 10000) def fbackward_button_clicked(self): self.music_player.setPosition(self.music_player.position() - 10000) def update_progress(self): progress_slider = self.window.findChild(QSlider, 'progress_slider') if self.music_player.duration != 0: progress_slider.setMaximum(self.music_player.duration()) total_sec = (self.music_player.duration() / 1000) % 60 total_min = (self.music_player.duration() / (1000 * 60)) % 60 if (total_sec < 10): total_time = ("%d:0%d" % (int(total_min), int(total_sec))) else: total_time = ("%d:%d" % (int(total_min), int(total_sec))) track_duration_label = self.window.findChild( QLabel, 'track_duration_label') track_duration_label.setText(total_time) progress = self.music_player.position() progress_slider.setValue(progress) cur_sec = (self.music_player.position() / 1000) % 60 cur_min = (self.music_player.position() / (1000 * 60)) % 60 if (cur_sec < 10): cur_time = ("%d:0%d" % (int(cur_min), int(cur_sec))) else: cur_time = ("%d:%d" % (int(cur_min), int(cur_sec))) track_current_label = self.window.findChild(QLabel, 'track_current_label') track_current_label.setText(cur_time) def scrub_progress(self): progress_slider = self.window.findChild(QSlider, 'progress_slider') self.music_player.setPosition(progress_slider.sliderPosition()) cur_min = (self.music_player.position() / 1000) % 60 cur_sec = (self.music_player.position() / (1000 * 60)) % 60 if (cur_sec < 10): cur_time = ("%d:0%d" % (int(cur_min), int(cur_sec))) else: cur_time = ("%d:%d" % (int(cur_min), int(cur_sec))) track_current_label = self.window.findChild(QLabel, 'track_current_label') track_current_label.setText(cur_time) def adjust_volume(self): volume_slider = self.window.findChild(QSlider, 'volume_slider') self.music_player.setVolume(volume_slider.sliderPosition())
class MainWindow(QMainWindow): """Display video loop and controls""" audio_changed = Signal(str) def __init__(self, parent=None): super().__init__(parent) # Default values. Updated if found in config.JSON self.use_qt_thread = False self.rhythm_algorithm = "multifeature" self.default_device_name = "" self.show_video_preview = True self.video_loop_bpm = 60 self.video_update_skip_ms = 100 self.limit_tempo_by_default = False self.tempo_lower_limit = 60.0 self.tempo_upper_limit = 120.0 self.screen = 0 self.spotify_track_id = "" self.read_config() self.setWindowTitle("Gandalf Enjoys Music") self.desktop = QApplication.desktop() self.audio = AudioDevice(self.default_device_name) self.input_devices = self.audio.get_input_device_names() self.audio_changed.connect(self.audio.change_audio_input) if self.use_qt_thread: self.bpm_extractor = BPMQt(self.update_bpm, algorithm=self.rhythm_algorithm) else: self.bpm_extractor = BPMmp(self.update_bpm, algorithm=self.rhythm_algorithm) self.audio.data_ready.connect(self.bpm_extractor.start_bpm_calculation) self.init_ui() def init_ui(self): dir_path = os.path.dirname(os.path.realpath(__file__)) file_location = dir_path + "/resources/gandalf_icon_256px.png" self.icon_pixmap = QPixmap(file_location) self.icon = QIcon(self.icon_pixmap) self.setWindowIcon(self.icon) self.setWindowIconText("Gandalf Enjoys Music") self.central = QWidget(self) self.setCentralWidget(self.central) self.layout = QVBoxLayout() self.lock_checkbox = QCheckBox("Manual tempo", self) self.lock_checkbox.clicked.connect(self.update_lock_checkbox) self.limit_layout = QVBoxLayout() self.limit_checkbox = QCheckBox("Limit tempo between:", self) self.limit_checkbox.setChecked(self.limit_tempo_by_default) self.limit_checkbox.clicked.connect(self.update_bpm_manually) self.init_video() if self.show_video_preview: self.setFixedSize(QSize(500, 350)) self.layout.addWidget(self.video_widget) else: self.setFixedSize(500, 100) self.fullscreen_button = QPushButton(self) self.fullscreen_button.setText("Go Fullscreen") self.layout.addWidget(self.fullscreen_button) self.fullscreen_button.clicked.connect(self.show_fullscreen) self.video_widget.fullscreen_changed.connect( self.update_button_text) self.video_widget.fullscreen_changed.connect( self.reset_video_position ) self.tempo_control_layout = QVBoxLayout() self.tempo_control_layout.addWidget(self.lock_checkbox) self.set_bpm_widget = QLineEdit("{:.1f}".format(self.old_bpm), self) self.set_bpm_widget.setMaxLength(5) self.set_bpm_widget.returnPressed.connect(self.update_bpm_manually) self.set_bpm_palette = QPalette() self.set_bpm_palette.setColor(QPalette.Text, Qt.gray) self.set_bpm_widget.setPalette(self.set_bpm_palette) self.set_bpm_widget.setFixedWidth(50) self.tempo_control_layout.addWidget(self.set_bpm_widget) self.limit_layout.addWidget(self.limit_checkbox) self.limits = QHBoxLayout() self.lower_bpm_widget = QLineEdit(str(self.tempo_lower_limit), self) self.lower_bpm_widget.setMaxLength(5) self.lower_bpm_widget.returnPressed.connect(self.update_lower_limit) self.lower_bpm_widget.setFixedWidth(50) self.limits.addWidget(self.lower_bpm_widget) self.upper_bpm_widget = QLineEdit(str(self.tempo_upper_limit), self) self.upper_bpm_widget.setMaxLength(5) self.upper_bpm_widget.returnPressed.connect(self.update_upper_limit) self.upper_bpm_widget.setFixedWidth(50) self.limits.addWidget(self.upper_bpm_widget) self.limit_layout.addLayout(self.limits) self.control_layout = QHBoxLayout() self.control_layout.addLayout(self.tempo_control_layout) self.control_layout.addLayout(self.limit_layout) self.save_settings_button = QPushButton("Save settings", self) self.save_settings_button.clicked.connect(self.save_config) self.control_layout.addWidget(self.save_settings_button) self.layout.addLayout(self.control_layout) self.device_layout = QHBoxLayout() self.audio_select_label = QLabel("Audio device:", self) self.device_layout.addWidget(self.audio_select_label) self.audio_selection = QComboBox(self) self.audio_selection.addItems(self.input_devices) self.audio_selection.currentIndexChanged.connect(self.audio_selection_changed) self.device_layout.addWidget(self.audio_selection) self.layout.addLayout(self.device_layout) self.central.setLayout(self.layout) def init_video(self): self.old_bpm = 1.0 self.video_widget = VideoWidget(self, self.show_video_preview, self.screen) self.media_player = QMediaPlayer(self.central) self.media_player.setVideoOutput(self.video_widget) self.playlist = QMediaPlaylist(self.media_player) dir_path = os.path.dirname(os.path.realpath(__file__)) file_location = dir_path + "/resources/video_long.mp4" self.video_file = QUrl.fromLocalFile(file_location) self.playlist.addMedia(self.video_file) self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.playlist.setCurrentIndex(0) self.media_player.setPlaylist(self.playlist) self.media_player.mediaStatusChanged.connect(self.handle_media_state_changed) self.media_player.play() self.change_playback_rate(self.video_loop_bpm) if not self.show_video_preview: self.video_widget.hide() def handle_media_state_changed(self, state): if state == QMediaPlayer.MediaStatus.BufferedMedia: playback_speed = self.old_bpm / self.video_loop_bpm self.media_player.setPlaybackRate(playback_speed) self.media_player.setPosition(0) def change_playback_rate(self, bpm): """Update playback speed for video loop.""" if bpm != self.old_bpm: # Prevent switching between double and half tempo during the same song in spotify track_id = get_spotify_track() if not self.lock_checkbox.isChecked()\ and not self.limit_checkbox.isChecked()\ and (math.isclose(bpm*2,self.old_bpm, rel_tol=3e-2)\ or math.isclose(bpm, self.old_bpm*2, rel_tol=3e-2))\ and track_id and track_id == self.spotify_track_id: self.spotify_track_id = track_id return self.spotify_track_id = track_id self.old_bpm = bpm playback_speed = bpm / self.video_loop_bpm # Workaround for a bug which causes irregular video playback speed # after changing playback rate current_position = self.media_player.position() self.media_player.setPlaybackRate(playback_speed) self.media_player.setPosition(current_position + self.video_update_skip_ms * playback_speed) def update_bpm(self, bpm, manual=False): if not manual: if self.lock_checkbox.isChecked(): return bpm = float(int(bpm+0.5)) if self.limit_checkbox.isChecked(): while bpm < self.tempo_lower_limit: bpm = bpm * 2.0 while bpm > self.tempo_upper_limit: bpm = bpm / 2.0 self.change_playback_rate(bpm) self.set_bpm_widget.setText("{:.1f}".format(self.old_bpm)) def update_bpm_manually(self): bpm = self.set_bpm_widget.text() try: bpm = float(bpm) if bpm < 1.0: raise ValueError except ValueError: return self.spotify_track_id = "" self.update_bpm(bpm, manual=True) def update_lock_checkbox(self): if self.lock_checkbox.isChecked(): self.set_bpm_palette = QPalette() self.set_bpm_palette.setColor(QPalette.Text, Qt.black) self.set_bpm_widget.setPalette(self.set_bpm_palette) self.set_bpm_widget.setReadOnly(False) else: self.set_bpm_palette = QPalette() self.set_bpm_palette.setColor(QPalette.Text, Qt.gray) self.set_bpm_widget.setPalette(self.set_bpm_palette) self.set_bpm_widget.setReadOnly(True) def update_lower_limit(self, value=None): if not value: value = self.lower_bpm_widget.text() try: value = float(value) if value < 1.0: raise ValueError except ValueError: return if value <= self.tempo_upper_limit / 2.0: self.tempo_lower_limit = value else: self.tempo_lower_limit = self.tempo_upper_limit / 2.0 self.lower_bpm_widget.setText("{:.1f}".format(self.tempo_lower_limit)) def update_upper_limit(self, value=None): if not value: value = self.upper_bpm_widget.text() try: value = float(value) if value < 1.0: raise ValueError except ValueError: return if value >= self.tempo_lower_limit * 2.0: self.tempo_upper_limit = value else: self.tempo_upper_limit = self.tempo_lower_limit * 2.0 self.upper_bpm_widget.setText("{:.1f}".format(self.tempo_upper_limit)) def audio_selection_changed(self, idx): self.audio_changed.emit(self.audio_selection.currentText()) @Slot() def show_fullscreen(self): self.reset_video_position() if self.video_widget.isFullScreen(): self.video_widget.hide() self.fullscreen_button.setText("Go Fullscreen") else: self.video_widget.setFullScreen(True) self.video_widget.setGeometry(self.desktop.screenGeometry(self.screen)) self.fullscreen_button.setText("Hide Fullscreen") @Slot() def reset_video_position(self): self.media_player.setPosition(0) @Slot(bool) def update_button_text(self, fullscreen_status): if fullscreen_status: self.fullscreen_button.setText("Hide Fullscreen") else: self.fullscreen_button.setText("Go Fullscreen") def read_config(self): with open("config.JSON") as config_file: config = json.load(config_file) if "no_multiprocess" in config: self.use_qt_thread = config["no_multiprocess"] if config.get("rhythm_algorithm_faster"): self.rhythm_algorithm = "degara" if config.get("default_device"): self.default_device_name = config["default_device"] if "show_video_preview" in config: self.show_video_preview = config.get("show_video_preview") if config.get("video_loop_bpm"): self.video_loop_bpm = config["video_loop_bpm"] if config.get("video_update_skip_time_ms"): self.video_update_skip_ms = config["video_update_skip_time_ms"] if config.get("limit_tempo_by_default"): self.limit_tempo_by_default = config["limit_tempo_by_default"] if config.get("tempo_lower_limit"): self.tempo_lower_limit = config["tempo_lower_limit"] if config.get("tempo_upper_limit"): self.tempo_upper_limit = config["tempo_upper_limit"] if "screen" in config: self.screen = config["screen"] @Slot() def save_config(self): fast_rhythm_algo = self.rhythm_algorithm == "degara" data = { "no_multiprocess": self.use_qt_thread, "rhythm_algorithm_faster": fast_rhythm_algo, "default_device": self.audio_selection.currentText(), "show_video_preview": self.show_video_preview, "video_loop_bpm": self.video_loop_bpm, "video_update_skip_time_ms": self.video_update_skip_ms, "limit_tempo_by_default": self.limit_checkbox.isChecked(), "tempo_lower_limit": self.tempo_lower_limit, "tempo_upper_limit": self.tempo_upper_limit, "screen": self.screen } with open("config.JSON", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=4)
class YoutubePlayer(QObject): titlesListChanged = Signal(list) def __init__(self, titles: List[Title] = [], widgetToPlay: QVideoWidget = None): QObject.__init__(self) self.__titles = titles self.__playlist = QMediaPlaylist(self) self.__player = QMediaPlayer(self) self.__videoWidget = widgetToPlay self.__player.setVideoOutput(self.__videoWidget) self.titlesListChanged.connect(self.resetPlayList) @property def titles(self): return self.__titles @titles.setter def titles(self, value): self.__titles = value self.titlesListChanged.emit(self.__titles) @Slot() def setTitles(self, titles: List[Title]): self.__titles = titles self.titlesListChanged.emit(self.__titles) @Slot() def resetPlayList(self, list_of_titles: List[Title]): self.__playlist.clear() for t in list_of_titles: url = t.link video = pafy.new(url) best = video.getbest() self.__playlist.addMedia(QMediaContent(QUrl(best.url))) self.__playlist.setCurrentIndex(0) self.__player.setPlaylist(self.__playlist) @Slot() def playVideo(self, index: int): self.__playlist.setCurrentIndex(index) self.__player.play() @Slot() def stopVideo(self): self.__player.stop() @Slot() def pauseVideo(self): if self.__player.state() == QMediaPlayer.PlayingState: self.__player.pause() else: self.__player.play()