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 MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.pblecture.clicked.connect(self.lectureClicked) self.ui.pbpause.clicked.connect(self.pauseClicked) self.ui.pbstop.clicked.connect(self.stopClicked) self.ui.pbmoins.clicked.connect(self.supprMedia) self.ui.pbplus.clicked.connect(self.ajouterMedia) self.ui.pbprecedent.clicked.connect(self.precedentClicked) self.ui.pbsuivant.clicked.connect(self.suivantClicked) self.mediaPlayer = QMediaPlayer() #creation de la variable mediaPlayer self.mediaPlayer.setVideoOutput( self.ui.ecran) #on projette la var mediaPlayer sur ecran. self.ui.dialVolume.valueChanged.connect(self.volumeChanged) self.mediaPlayer.durationChanged.connect(self.mediaDurationChanged) self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged) self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected) # Commande qui permet de lancer le film (depuis le début) mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi")) self.mediaPlayer.setMedia(mediaContent) #def slideChanged(self): # self.mediaPlayer.position() # self.ui.timeline.setValue() def ajouterMedia(self): nomMedia = QFileDialog.getOpenFileName( self, "ChoixFilm", "c:/Users/AELION/PycharmProjects/lect_video", "(*.avi *.mp4)") fInfo = QFileInfo(nomMedia[0]) fShortName = fInfo.baseName() item = QListWidgetItem(fShortName) item.setToolTip(nomMedia[0]) self.ui.listWidget.addItem(item) def suivantClicked(self): currentItemRow = self.ui.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.ui.listWidget.count() self.ui.listWidget.setCurrentRow((currentItemRow + 1) % totalItems) self.mediaSelected() def precedentClicked(self): currentItemRow = self.ui.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.ui.listWidget.count() self.ui.listWidget.setCurrentRow((currentItemRow - 1) % totalItems) self.mediaSelected() def supprMedia(self): rowItem = self.ui.listWidget.currentRow() if rowItem != -1: #au cas ou on appuie sur Supp et qu'il n'y a pas d'objet self.ui.listWidget.takeItem(rowItem) def mediaSelected(self): currentItem = self.ui.listWidget.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def mediaDurationChanged(self): self.ui.debut.setText("00:00:00") mediaDuration = self.mediaPlayer.duration( ) #recoit le temps total en Millisec self.ui.timeline.setRange( 0, mediaDuration ) #découpe le timeline proportionnelement au temps en millisec totalTimeMedia = QTime(0, 0, 0) totalTimeMedia = totalTimeMedia.addMSecs( mediaDuration) #convertit le temps total en h:m:s self.ui.fin.setText(totalTimeMedia.toString("HH:mm:ss")) def mediaPositionChanged(self): mediaPosition = self.mediaPlayer.position() self.ui.timeline.setValue(mediaPosition) currentTimeMedia = QTime( 0, 0, 0, ) currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition) self.ui.debut.setText(currentTimeMedia.toString("HH:mm:ss")) def volumeChanged(self): self.mediaPlayer.setVolume(self.ui.dialVolume.value()) self.ui.labelVol.setText(str(self.ui.dialVolume.value()) + "%") def lectureClicked(self): print("Lecture!!") self.mediaPlayer.play() def pauseClicked(self): print("Pause !!") if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() elif self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() def stopClicked(self): print("Stop!!") self.mediaPlayer.stop()
class MainWindow(QtWidgets.QMainWindow): def __init__(self, widget, data): # super().__init__() QtWidgets.QMainWindow.__init__(self) self.setWindowTitle("Simple Podcast Utility") self.widget = widget self.podcast = podcast self.items = None self.setCentralWidget(widget) self.player = QMediaPlayer() self.media = None # Menu self.menu = QtWidgets.QMenuBar() # self.menu = self.menuBar() self.menu.setNativeMenuBar(False) self.setMenuBar(self.menu) self.file_menu = self.menu.addMenu("File") add_action = QtWidgets.QAction("Add", self) exit_action = QtWidgets.QAction("Exit", self) self.file_menu.addAction(add_action) self.file_menu.addAction(exit_action) add_action.triggered.connect(self.add_podcast) exit_action.triggered.connect(self.exit_app) names = self.get_podcast_name_list(self.podcast.get_subscribe()) self.widget.update_podcasts_list(names) self.widget.podcasts_list.clicked.connect(self.update_item_list) self.widget.item_list.doubleClicked.connect(self.start_play_item) self.widget.progress_bar.sliderPressed.connect( self.on_select_progress_begin) self.widget.progress_bar.sliderReleased.connect( self.on_select_progress_end) self.widget.progress_bar.sliderMoved.connect( self.on_select_progress_move) self.timer = QTimer() self.timer.timeout.connect(self.on_timer) self.timer.start(1000) self.begin_seek = False self.play_url = None @Slot() def on_select_progress_begin(self): self.begin_seek = True @Slot() def on_select_progress_move(self, value): self.widget.playtime_label.setText(time_string(value)) @Slot() def on_select_progress_end(self): if self.player.isSeekable(): value = self.widget.progress_bar.value() self.player.setPosition(value * 1000) self.begin_seek = False else: print('not seekable') @Slot() def on_timer(self): player = self.player if not self.begin_seek: if player.state() == QMediaPlayer.PlayingState: playtime = player.position() // 1000 self.widget.set_progress(playtime) @Slot() def start_play_item(self, index): i = index.row() if self.player.state() == QMediaPlayer.PlayingState: self.player.stop() self.begin_seek = False self.play_url = self.items[i]['url'] self.media = QMediaContent(self.items[i]['url']) self.player.setMedia(self.media) self.player.play() self.widget.set_duration(self.items[i]['duration']) @Slot() def update_item_list(self, index): i = index.row() feed_url = self.podcast.podcasts[i]['feedUrl'] self.items = podcast.get_feed(feed_url) names = self.get_item_name_list(self.items) self.widget.update_items_list(names) @Slot() def subscribe(self, index): i = index.row() self.podcast.subscribe(self.search_r[i]) names = self.get_podcast_name_list(self.podcast.get_subscribe()) self.widget.update_podcasts_list(names) @Slot() def search(self): self.search_r = self.podcast.search(self.dialog.edit.text()) names = [] if self.search_r: for i in self.search_r: names.append(i['collectionName']) model = QStringListModel(names) self.dialog.result_list.setModel(model) def get_item_name_list(self, items): names = [] for item in items: names.append(item['title']) return names def get_podcast_name_list(self, podcasts): names = [] for item in podcasts: names.append(item['collectionName']) return names @Slot() def add_podcast(self, checked): self.dialog = SearchDialog(self.subscribe, self.search) self.dialog.exec_() self.dialog = None @Slot() def exit_app(self, checked): print('exit app') QtWidgets.QApplication.quit()
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) #Connection du decodeur et lecteur self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.ui.ecranWidget) #chargement du media mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi")) self.mediaPlayer.setMedia(mediaContent) #connect push boutons self.ui.pbLecture.clicked.connect(self.lectureClicked) self.ui.pbPause.clicked.connect(self.pauseClicked) self.ui.pbStop.clicked.connect(self.stopClicked) self.ui.dialVolume.valueChanged.connect(self.volControl) self.ui.nivoVolume.setText(str(self.ui.dialVolume.value())) self.ui.nivoVolume.setText('{}%'.format(str(self.ui.dialVolume.value()))) self.mediaPlayer.durationChanged.connect(self.affTemp) self.mediaPlayer.positionChanged.connect(self.avanceTemp) self.ui.barreLect.valueChanged.connect(self.avanceSlider) self.ui.pbPlus.clicked.connect(self.pbPlusCtrl) self.ui.pbMoins.clicked.connect(self.pbMoinsCtrl) self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected) self.ui.pbSuivant.clicked.connect(self.suivantBouton) self.ui.pbPrecedent.clicked.connect(self.precedentBouton) #fonction qui gere les click def lectureClicked(self): self.mediaPlayer.play() def pauseClicked(self): if self.mediaPlayer.state() == QMediaPlayer.PausedState : self.mediaPlayer.play() else : self.mediaPlayer.pause() def stopClicked(self): self.mediaPlayer.stop() def volControl(self): self.mediaPlayer.setVolume(self.ui.dialVolume.value()) self.ui.nivoVolume.setText('{}%'.format(str(self.ui.dialVolume.value()))) def affTemp(self): tempTotl = QTime(0, 0, 0) tempTotl = tempTotl.addMSecs(self.mediaPlayer.duration() - self.mediaPlayer.position()) posTemp = QTime(0, 0, 0) posTemp = posTemp.addMSecs((self.mediaPlayer.position())) self.ui.tempRestant.setText("- {}".format(tempTotl.toString("HH:mm:ss"))) self.ui.tempLecture.setText(posTemp.toString("HH:mm:ss")) self.ui.barreLect.setRange(0,self.mediaPlayer.duration()) def avanceTemp(self): tempTotl= QTime(0,0,0) tempTotl = tempTotl.addMSecs(self.mediaPlayer.duration()-self.mediaPlayer.position()) posTemp= QTime(0,0,0) posTemp = posTemp.addMSecs((self.mediaPlayer.position())) self.ui.tempRestant.setText("-{}".format(tempTotl.toString("HH:mm:ss"))) self.ui.tempLecture.setText(posTemp.toString("HH:mm:ss")) self.ui.barreLect.setSliderPosition(self.mediaPlayer.position()) def avanceSlider(self): self.mediaPlayer.setPosition(self.ui.barreLect.sliderPosition()) def pbPlusCtrl(self): fileName = QFileDialog.getOpenFileName(self,"choix film","/home","Film(*.avi *.mp4)") fInfo = QFileInfo(fileName[0]) fShortName = fInfo.baseName() item = QListWidgetItem(fShortName) item.setToolTip(fileName[0]) self.ui.listWidget.addItem(item) print(item.toolTip().title()) def pbMoinsCtrl(self): rowItem= self.ui.listWidget.currentRow() if rowItem != -1: self.ui.listWidget.takeItem(rowItem) def mediaSelected(self): currentItem = self.ui.listWidget.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def suivantBouton(self): if self.ui.listWidget.count() != 0 : self.ui.listWidget.setCurrentRow((self.ui.listWidget.currentRow()+1) % self.ui.listWidget.count() ) mediaContent = QMediaContent(QUrl.fromLocalFile(self.ui.listWidget.currentItem().toolTip())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def precedentBouton(self): if self.ui.listWidget.count() != 0 : self.ui.listWidget.setCurrentRow((self.ui.listWidget.currentRow()-1) % self.ui.listWidget.count() ) mediaContent = QMediaContent(QUrl.fromLocalFile(self.ui.listWidget.currentItem().toolTip())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked()
class VedioUI(QWidget): def __init__(self): super(VedioUI, self).__init__() #定义视频总时长(分钟/秒钟),当前播放到的时间(单位ms) self.vedio_duration_total = '00:00' self.vedio_duration_now = 0 #定义窗口和播放器 self.player = QMediaPlayer(self) self.video_widget = myQVideoWidget() self.video_widget.resize(self.width(), self.height()) self.player.setVideoOutput(self.video_widget) #设置按钮 self.start_pause_btn = QPushButton(self) self.stop_btn = QPushButton(self) self.fast_btn = QPushButton(self) self.back_btn = QPushButton(self) self.screenshot_btn = QPushButton(self) #设定时间块 self.time_label = QLabel(self) self.time_label.setText('--/--') self.progress_slider = QSlider(self) self.progress_slider.setEnabled(False) #没有视频播放时,进度条不可使用 self.progress_slider.setOrientation(Qt.Horizontal) #进度条移动事件 self.progress_slider.sliderMoved.connect(self.move_position) #设定图标 self.start_pause_btn.setIcon(QIcon('ico/pause.png')) self.stop_btn.setIcon(QIcon('ico/stop.png')) self.fast_btn.setIcon(QIcon('ico/fast_forward.png')) self.back_btn.setIcon(QIcon('ico/back_forward.png')) self.screenshot_btn.setIcon(QIcon('ico/screenshot.png')) #点击链接 self.start_pause_btn.clicked.connect( lambda: self.btn_func(self.start_pause_btn)) self.stop_btn.clicked.connect(lambda: self.btn_func(self.stop_btn)) self.fast_btn.clicked.connect(lambda: self.btn_func(self.fast_btn)) self.back_btn.clicked.connect(lambda: self.btn_func(self.back_btn)) self.screenshot_btn.clicked.connect( lambda: self.btn_func(self.screenshot_btn)) #获取视频时间 self.player.durationChanged.connect(self.get_duration) #更新进度条 self.player.positionChanged.connect(self.update_position) #界面布局 self.h1_layout = QHBoxLayout() self.h2_layout = QHBoxLayout() self.v_layout = QVBoxLayout() self.h1_layout.addWidget(self.progress_slider) self.h1_layout.addWidget(self.time_label) self.h2_layout.addWidget(self.back_btn) self.h2_layout.addWidget(self.start_pause_btn) self.h2_layout.addWidget(self.stop_btn) self.h2_layout.addWidget(self.fast_btn) self.h2_layout.addWidget(self.screenshot_btn) self.v_layout.addWidget(self.video_widget) self.v_layout.addLayout(self.h1_layout) self.v_layout.addLayout(self.h2_layout) self.v_layout.setStretch(0, 1) self.setLayout(self.v_layout) #设定窗口名称及大小 self.setWindowTitle("视频播放") self.resize(1024, 768) #居中显示 self.center() #文件加载与播放 def vedio_show(self, vedio_dir=None): if vedio_dir: #添加播放文件 self.media_content = QMediaContent(QUrl.fromLocalFile(vedio_dir)) self.player.setMedia(self.media_content) #声音 self.player.setVolume(50) #开始播放 self.player.play() else: QMessageBox.critical(self,'文件打开失败',\ '1.文件扩展名与文件类型不匹配!\n2.路径中请勿含有中文字符!\n3.文件损坏!\n4.文件无法读取!') exit(-1) #按键链接 def btn_func(self, btn): pass if btn == self.start_pause_btn: # 0停止状态 1正在播放 2暂停状态 if self.player.state() == 1: self.player.pause() self.start_pause_btn.setIcon(QIcon('ico/start.png')) else: self.player.play() self.start_pause_btn.setIcon(QIcon('ico/pause.png')) # elif btn == self.stop_btn: # elif btn == self.fast_btn: # elif btn == self.back_btn: elif btn == self.screenshot_btn: self.player.pause() self.start_pause_btn.setIcon(QIcon('ico/start.png')) QMessageBox.information(self, "提示", '请框取集装箱编号区域') #鼠标修改 self.video_widget.setCursor(Qt.CrossCursor) self.video_widget.select_on() #让屏幕居中 def center(self): #获取屏幕坐标系 screen = QDesktopWidget().screenGeometry() #获取窗口坐标系 size = self.geometry() newLeft = (screen.width() - size.width()) / 2 newTop = (screen.height() - size.height()) / 2 self.move(newLeft, newTop) #将ms转化成 分钟:秒钟 def time_conversion(self, d): seconds = int(d / 1000) minutes = int(seconds / 60) seconds -= minutes * 60 return '{}:{}'.format(minutes, seconds) #设置QLable的时间 def time_set(self, d_now='00:00', d_total='00:00'): if d_now == '00:00': self.time_label.setText('--/--') self.start_pause_btn.setIcon(QIcon('ico/start.png')) else: self.time_label.setText(d_now + '/' + d_total) #获取视频总时长,并设定进度条可用 def get_duration(self, p): self.progress_slider.setRange(0, p) self.vedio_duration_total = self.time_conversion(p) self.progress_slider.setEnabled(True) #更新进度条和时间 def update_position(self, p): self.progress_slider.setValue(p) self.vedio_duration_now = p self.time_set(self.time_conversion(self.vedio_duration_now), self.vedio_duration_total) #移动滑块后更新视频,更新时间显示 def move_position(self, p): self.player.setPosition(p) self.vedio_duration_now = p self.time_set(self.time_conversion(self.vedio_duration_now), self.vedio_duration_total)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # Create widgets self.ui = Ui_MainWindow() self.ui.setupUi(self) self.mediaPlayer = QMediaPlayer() self.playlist = QMediaPlaylist() #mediaContent1 = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi")) #mediaContent2=QMediaContent(QUrl.fromLocalFile("Doom.Patrol1.mp4")) #self.playlist.addMedia(mediaContent1) #self.playlist.addMedia(mediaContent2) #self.playlist.setCurrentIndex(1) #self.mediaPlayer.setMedia(self.playlist) self.mediaPlayer.setVideoOutput(self.ui.wvideo) self.ui.ltemps.setText("") self.ui.lduree.setText("") self.ui.dialVolume.setValue(0) self.ui.lvolume_2.setText(str(self.ui.dialVolume.value())) self.ui.pblecture.clicked.connect(self.lectureClicked) self.ui.pbpause.clicked.connect(self.pauseClicked) self.ui.pbstop.clicked.connect(self.stopClicked) self.ui.pbsuivant.clicked.connect(self.suivantClicked) self.ui.pbprecedent.clicked.connect(self.precedentClicked) self.ui.pbajouter.clicked.connect(self.ajouter2) self.ui.pbsupprimer.clicked.connect(self.supprimer) self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected2) self.ui.dialVolume.valueChanged.connect(self.volumeChanged) #self.mediaPlayer.positionChanged.connect(self.tempsChanged) self.mediaPlayer.positionChanged.connect(self.lectureEnCours) #self.mediaPlayer.positionChanged.connect(self.progressionChanged) self.ui.stpscourant.sliderMoved.connect(self.sliderMove) def sliderMove(self): self.mediaPlayer.setPosition(self.ui.stpscourant.value()) def lectureEnCours(self): mediaPosition = self.mediaPlayer.position() currentTimeMedia = QTime(0, 0, 0) currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition) mediaDuration = self.mediaPlayer.duration() totalTimeMedia = QTime(0, 0, 0) totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration) self.ui.ltemps.setText(currentTimeMedia.toString("HH:mm:ss")) self.ui.lduree.setText(totalTimeMedia.toString("HH:mm:ss")) self.ui.stpscourant.setRange(0, self.mediaPlayer.duration()) self.ui.stpscourant.setValue(self.mediaPlayer.position()) def lectureClicked(self): print("Lecture!!") self.mediaPlayer.play() def pauseClicked(self): print("pause!!") if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def stopClicked(self): print("stop!!") self.mediaPlayer.stop() def suivantClicked(self): print("suivant!!") currentItemRow = self.ui.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.ui.listWidget.count() self.ui.listWidget.setCurrentRow((currentItemRow + 1) % totalItems) self.mediaSelected2() def precedentClicked(self): print("precedent!!") currentItemRow = self.ui.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.ui.listWidget.count() self.ui.listWidget.setCurrentRow((currentItemRow - 1) % totalItems) self.mediaSelected2() def volumeChanged(self): self.ui.dialVolume.setMaximum(100) self.mediaPlayer.setVolume(self.ui.dialVolume.value()) self.ui.lvolume_2.setText(str(self.ui.dialVolume.value())) def ajouter(self): nomMedia = QFileDialog.getOpenFileName( self, "Choix Film", "C:/Users/AELION/PycharmProjects/videoLHector", "Movie Files (*.avi *.mp4)") item = QListWidgetItem(nomMedia[0]) self.ui.listWidget.addItem(item) def ajouter2(self): nomMedia = QFileDialog.getOpenFileName( self, "Choix Film", "C:/Users/AELION/PycharmProjects/videoLHector", "Movie Files (*.avi *.mp4)") fInfo = QFileInfo(nomMedia[0]) fShortName = fInfo.baseName() print(fShortName) item = QListWidgetItem(fShortName) item.setToolTip(nomMedia[0]) self.ui.listWidget.addItem(item) def supprimer(self): rowItem = self.ui.listWidget.currentRow() if rowItem != -1: self.ui.listWidget.takeItem(rowItem) def mediaSelected1(self): currentItem = self.ui.listWidget.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def mediaSelected2(self): currentItem = self.ui.listWidget.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked()
class EditorWidget(QWidget): """Widget which contain the editor.""" def __init__(self, plugin_manager): super(EditorWidget, self).__init__() os.environ[ 'QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation' self.plugin_manager = plugin_manager #parent layout self.v_box = QVBoxLayout() self.h_box = QHBoxLayout() # parent splitter for the text and numbers self.text_h_box = QSplitter(Qt.Horizontal) self.text_h_box.splitterMoved.connect(self.on_text_changed) self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat) self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH, QSettings.IniFormat) self.theme = self.settings.value(c.THEME, defaultValue=c.THEME_D) # font settings self.font = QFont( self.settings.value(c.FONT, defaultValue="Arial", type=str)) self.font.setPointSize( self.settings.value(c.FONT_SIZE, defaultValue=16, type=int)) # the text widget itself self.text = QPlainTextEdit() self.text.setFont(self.font) self.text.textChanged.connect(self.on_text_changed) self.text.setFocusPolicy(Qt.StrongFocus) # the number text widget to show the row numbers self.numbers = QPlainTextEdit() self.numbers.setFont(self.font) self.numbers.setReadOnly(True) self.numbers.setMinimumWidth(20) self.numbers.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.numbers.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.numbers.setLineWrapMode(QPlainTextEdit.NoWrap) self.numbers.setFocusPolicy(Qt.NoFocus) self.numbers.setFrameStyle(QFrame.NoFrame) self.numbers.setStyleSheet("background-color: rgba(0,0,0,0%)") # sync the text widget and number widget self.text_bar = self.text.verticalScrollBar() self.number_bar = self.numbers.verticalScrollBar() #self.number_bar.valueChanged.connect(self.text_bar.setValue) self.text_bar.valueChanged.connect(self.number_bar.setValue) # add them into their layout self.text_h_box.addWidget(self.numbers) self.text_h_box.addWidget(self.text) self.text_h_box.setSizes([10, 700]) # layout which holds the media controls in the bottom self.media_controls = QHBoxLayout() self.media_controls_settings = QVBoxLayout() self.media_controls_slider_h_box = QHBoxLayout() # direct player controls self.btn_size = 75 self.play_icon = QIcon( os.path.join(c.ICON_PATH, self.theme, "play.png")) self.pause_icon = QIcon( os.path.join(c.ICON_PATH, self.theme, "pause.png")) self.play_btn = QPushButton(icon=self.play_icon) self.play_btn.clicked.connect(self.on_play) self.play_btn.setFixedSize(self.btn_size, self.btn_size) self.play_btn.setIconSize(QSize(self.btn_size, self.btn_size)) self.play_btn.setFlat(True) self.play_btn.setShortcut(QKeySequence().fromString( self.keyboard_settings.value(c.PLAY_PAUSE_KEY, defaultValue=""))) self.forward_btn = QPushButton( icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "forward.png"))) self.forward_btn.clicked.connect(self.on_forward) self.forward_btn.setFixedSize(self.btn_size, self.btn_size) self.forward_btn.setIconSize(QSize(self.btn_size, self.btn_size)) self.forward_btn.setFlat(True) self.forward_btn.setShortcut(QKeySequence().fromString( self.keyboard_settings.value(c.FORWARD_KEY, defaultValue=""))) self.backward_btn = QPushButton( icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "backward.png"))) self.backward_btn.clicked.connect(self.on_backward) self.backward_btn.setFixedSize(self.btn_size, self.btn_size) self.backward_btn.setIconSize(QSize(self.btn_size, self.btn_size)) self.backward_btn.setFlat(True) self.backward_btn.setShortcut(QKeySequence().fromString( self.keyboard_settings.value(c.BACKWARDS_KEY, defaultValue=""))) # add them to the layout self.media_controls.addStretch() self.media_controls.addWidget(self.backward_btn) self.media_controls.addWidget(self.play_btn) self.media_controls.addWidget(self.forward_btn) self.media_controls.addStretch(4) # slider which shows the current time self.time_slider = QSlider(Qt.Horizontal) self.time_slider.sliderMoved.connect(self.on_time_slider_moved) # label on the right of the slider, which shows the current time self.time_label = QLabel("00:00/00:00") self.media_controls_slider_h_box.addWidget(self.time_slider) self.media_controls_slider_h_box.addWidget(self.time_label) # icons for the other sliders self.vol_icon = QIcon( os.path.join(c.ICON_PATH, self.theme, "volume.png")).pixmap(QSize(32, 32)) self.rate_icon = QIcon( os.path.join(c.ICON_PATH, self.theme, "playbackrate.png")).pixmap(QSize(32, 32)) self.rewind_icon = QIcon( os.path.join(c.ICON_PATH, self.theme, "time.png")).pixmap(QSize(32, 32)) # display the icons through labels self.vol_icon_label = QLabel() self.vol_icon_label.setPixmap(self.vol_icon) self.rate_icon_label = QLabel() self.rate_icon_label.setPixmap(self.rate_icon) self.rewind_rewind_label = QLabel() self.rewind_rewind_label.setPixmap(self.rewind_icon) # init of the other sliders self.vol_slider = QSlider(Qt.Horizontal) self.vol_slider.sliderMoved.connect(self.on_vol_slider_moved) self.vol_slider.setFixedWidth(250) self.vol_slider.setRange(1, 100) self.rate_slider = QSlider(Qt.Horizontal) self.rate_slider.sliderMoved.connect(self.on_rate_slider_moved) self.rate_slider.setFixedWidth(250) self.rate_slider.setRange(1, 20) self.rewind_time = 10 self.rewind_slider = QSlider(Qt.Horizontal) self.rewind_slider.sliderMoved.connect(self.on_rewind_slider_moved) self.rewind_slider.setFixedWidth(250) self.rewind_slider.setRange(1, 60) self.rewind_slider.setValue(self.rewind_time) # labels for the values self.vol_label = QLabel() self.rate_label = QLabel() self.rewind_label = QLabel() # create hbox for each of the three sliders self.vol_h_box = QHBoxLayout() self.vol_h_box.addWidget(self.vol_label) self.vol_h_box.addWidget(self.vol_slider) self.vol_h_box.addWidget(self.vol_icon_label) self.rate_h_box = QHBoxLayout() self.rate_h_box.addWidget(self.rate_label) self.rate_h_box.addWidget(self.rate_slider) self.rate_h_box.addWidget(self.rate_icon_label) self.rewind_h_box = QHBoxLayout() self.rewind_h_box.addWidget(self.rewind_label) self.rewind_h_box.addWidget(self.rewind_slider) self.rewind_h_box.addWidget(self.rewind_rewind_label) # group them together in a vlayout self.media_controls_settings.addLayout(self.vol_h_box) self.media_controls_settings.addLayout(self.rewind_h_box) self.media_controls_settings.addLayout(self.rate_h_box) # add this layout to the layout which already contains the buttons self.media_controls.addLayout(self.media_controls_settings) self.word_by_word_actions = QListWidget() self.word_by_word_actions.setMaximumWidth(150) self.h_box.addWidget(self.text_h_box) self.h_box.addWidget(self.word_by_word_actions) # group all ungrouped layouts and widgets to the parent layout self.v_box.addLayout(self.h_box, 10) self.v_box.addLayout(self.media_controls_slider_h_box, 1) self.v_box.addLayout(self.media_controls, 1) # set parent layout self.setLayout(self.v_box) # init media_player self.media_player = QMediaPlayer() self.video_widget = QVideoWidget() self.video_widget.setGeometry(200, 200, 500, 300) self.video_widget.setWindowTitle("Output") self.media_player.setVideoOutput(self.video_widget) self.media_player.positionChanged.connect(self.on_position_change) self.media_player.durationChanged.connect(self.on_duration_change) self.vol_slider.setValue(self.media_player.volume()) self.rate_slider.setValue(int(self.media_player.playbackRate() * 10)) self.on_vol_slider_moved(self.media_player.volume()) self.on_rate_slider_moved(self.media_player.playbackRate() * 10) self.on_rewind_slider_moved(self.rewind_time) self.activate_text_modules = False self.get_text_modules() self.text_option_on = QTextOption() self.text_option_on.setFlags( QTextOption.ShowTabsAndSpaces | QTextOption.ShowLineAndParagraphSeparators) self.text_option_off = QTextOption() self.transcription_meta_data = None self.word_pos = -1 self.word_start_time = None self.word_end_time = None self.tcf_highlight = QTextCharFormat() self.tcf_highlight.setBackground(Qt.red) self.tcf_normal = QTextCharFormat() self.tcf_normal.setBackground(Qt.transparent) self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS, defaultValue=True, type=bool) def on_position_change(self, position): """Is executed when media is played (position is changed) Args: position: Current position (ms) of the media player. """ self.time_slider.setValue(position) self.time_label.setText( create_time_string(position, self.media_player.duration())) if self.word_end_time is None: return if position > self.word_end_time: self.on_play() self.word_start_time = None self.word_end_time = None def on_duration_change(self, duration): """Is executed when duration of the media changes. Args: duration: duration of the media. """ self.time_slider.setRange(0, duration) self.time_label.setText( create_time_string(0, self.media_player.duration())) def on_time_slider_moved(self, value): """Is executed when the time slider was moved. Args: value: current value of the slider. """ self.media_player.setPosition(value) def on_vol_slider_moved(self, value): """Is executed when the volume slider is moved. Args: value: current value of the slider. """ self.media_player.setVolume(value) self.vol_label.setText(str(value) + "%") def on_rate_slider_moved(self, value): """Is executed when the rate slider is moved. Args: value: current value of the slider. """ self.media_player.setPlaybackRate(value / 10) self.rate_label.setText(str(value / 10) + "x") def on_rewind_slider_moved(self, value): """Is executed when the rewind slider is moved. Args: value: current value of the slider. """ self.rewind_time = value self.rewind_label.setText(str(value) + "s") def on_play(self): """Is executed when the play or pause button is pressed.""" if self.media_player.state() == QMediaPlayer.PlayingState: self.media_player.pause() self.play_btn.setIcon(self.play_icon) else: self.media_player.play() self.play_btn.setIcon(self.pause_icon) def on_forward(self): """Is executed when the forward button is pressed.""" self.media_player.setPosition(self.media_player.position() + self.rewind_time * 1000) def on_backward(self): """Is executed when the backward button is pressed.""" self.media_player.setPosition(self.media_player.position() - self.rewind_time * 1000) def on_text_changed(self): """Is executed when the text changed Calculates the line numbers and sets the text modules if activated. """ lines = int( self.text.document().documentLayout().documentSize().height()) self.numbers.setPlainText("") text = "" for i in range(1, lines + 1): text = text + str(i) + "\n" self.numbers.setPlainText(text) self.number_bar.setSliderPosition(self.text_bar.sliderPosition()) new_text = self.text.toPlainText() if self.activate_text_modules == True: for key in self.text_modules.keys(): to_replace = " " + key + " " to_replace_with = " " + self.text_modules[key] + " " new_text = new_text.replace(to_replace, to_replace_with) if self.text.toPlainText() != new_text: old_pos = self.text.textCursor().position() self.text.setPlainText(new_text) cursor = self.text.textCursor() cursor.setPosition(old_pos, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.EndOfWord) cursor.movePosition(QTextCursor.NextCharacter) self.text.setTextCursor(cursor) def show_video(self): """Shows or hides the video feed.""" if self.video_widget.isVisible(): self.video_widget.hide() else: self.video_widget.show() def open_project(self, project_folder_path): """Opens a project. Args: project_folder_path: folder of the project which should be opened. """ self.project_folder_path = project_folder_path self.media_file = file_util.get_file(self.project_folder_path, c.CON_COPY_POSTFIX) if self.media_file is None: self.hide() return self.media_player.setMedia( QMediaContent(QUrl.fromLocalFile(self.media_file))) self.transcription_path = file_util.get_file(self.project_folder_path, c.TRANSCRIPTION) if self.transcription_path is None: self.hide() return with open(self.transcription_path, 'r') as f: text = f.read() self.text.setPlainText(text) self.transcription_meta_data = file_util.get_value_from_shelve( self.project_folder_path, c.TRANSCRIPTION_META_DATA) print(self.transcription_meta_data) def change_font(self, new_font, new_size): """Changes the font. Args: new_font: Name of the new font. new_size: New font size. """ self.font = QFont(new_font) self.font.setPointSize(int(new_size)) self.text.setFont(self.font) self.numbers.setFont(self.font) self.settings.setValue(c.FONT_SIZE, int(new_size)) self.settings.setValue(c.FONT, new_font) def get_text_modules(self): """Gets the saved text_modules from the settings.""" self.text_modules = self.settings.value(c.TEXT_MODULES, defaultValue={}) def show_special_characters(self, bol): """Displays the special characters. Args: bol: true or false. """ if bol: self.text.document().setDefaultTextOption(self.text_option_on) else: self.text.document().setDefaultTextOption(self.text_option_off) def on_word_by_word(self): """Selects the next or first word in the on word by word editing mode. For that purpose th word_postion is increased and the next word is marked via the textcursor. If everything works correctly the population of the list will be started. """ self.word_pos += 1 #if self.media_player.state() == QMediaPlayer.PlayingState: # return if self.word_pos > len(self.text.toPlainText().split()) - 1: self.reset_word_by_word() return cursor = self.text.textCursor() if self.word_pos == 0: self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS, defaultValue=True, type=bool) cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) self.text.setEnabled(False) else: cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) self.text.setTextCursor(cursor) selected_word = cursor.selectedText() if not selected_word: self.word_pos -= 1 self.on_word_by_word() return # change to find all meta data meta_data_with_word = self.find_meta_data(selected_word) self.populate_word_actions(selected_word, meta_data_with_word) def on_word_by_word_prev(self): """Same as word for word but selects to the previous word.""" if self.word_pos < 1: return self.word_pos -= 2 cursor = self.text.textCursor() count = 0 cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) while count < self.word_pos: cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) count += 1 self.text.setTextCursor(cursor) self.on_word_by_word() def reset_word_by_word(self): """Resets the word by word editing mode and goes back to the normal editing.""" self.word_pos = -1 self.play_to = -1 self.text.setEnabled(True) self.word_by_word_actions.clear() cleaned = self.text.textCursor() cleaned.clearSelection() self.text.setTextCursor(cleaned) def populate_word_actions(self, selected, word_meta_data): """Calls the plugin_manager to get alle the word for word buttons and initalize the hear again buttons. Args: selected: The selected word. word_meta_data: The meta_data fr the word. """ self.word_by_word_actions.clear() if self.word_pos == len(self.text.toPlainText().split()): return self.plugin_manager.get_word_by_word_actions(selected, word_meta_data, self.word_pos) btns = [] for meta_data in word_meta_data: media_btn = HearButton(self, meta_data) btns.append(media_btn) self.add_new_word_by_word_action(btns, "Hear again", selected, self.word_pos) def add_new_word_by_word_action(self, btns, name, word, word_pos): """Adds a new word by word action. Args: btns: The buttons to add. name: The (plugin-)name of the buttons. word: The word for which these buttons are. word_pos: The word position. """ if not self.show_empty_buttons and len(btns) == 0: return if self.word_pos != word_pos: print("old item", word, word_pos, self.word_pos) return group_item = QListWidgetItem() group_item.setFlags(Qt.ItemIsSelectable) label = QLabel(name) label.setFixedSize(self.word_by_word_actions.width() - 15, 30) label.setContentsMargins(5, 0, 0, 0) label.setWordWrap(True) group_item.setSizeHint(label.size()) self.word_by_word_actions.addItem(group_item) self.word_by_word_actions.setItemWidget(group_item, label) for btn in btns: btn.setFixedSize(self.word_by_word_actions.width() - 15, 30) item = QListWidgetItem() item.setSizeHint(btn.size()) item.setFlags(Qt.ItemIsSelectable) self.word_by_word_actions.addItem(item) self.word_by_word_actions.setItemWidget(item, btn) def find_meta_data(self, word): """Gets all the meta_data for the given word. Args: word: The word for which the meta_data should be found. Returns: The meta_data """ meta_data_with_word = [] for m_d in self.transcription_meta_data: if m_d.get(c.WORD) == word.lower(): meta_data_with_word.append(m_d) return meta_data_with_word def replace_selection(self, new_word): """Replace the selection with the given word Args: new_word: The replacement. """ cursor = self.text.textCursor() old_cursor_pos = cursor.position() cursor.insertText(new_word) cursor.setPosition(old_cursor_pos, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.MoveAnchor) self.text.setTextCursor(cursor) self.word_by_word_actions.clear() def get_selection(self): """Returns the current selection Returns: The current selection. """ return self.text.textCursor().selectedText() def get_text(self): """Returns the current text Returns: The current text. """ return self.text.toPlainText() def set_text(self, new_text, restore_line_breaks=False): """Replace the text with the new text. Args: new_text: The new text. restore_line_breaks: If true, tries to restore the line breaks. (Default value = False) """ cursor = self.text.textCursor() old_cursor_pos = cursor.position() if restore_line_breaks: self.set_text_with_line_breaks(new_text) else: self.text.setPlainText(new_text) cursor.setPosition(old_cursor_pos, QTextCursor.MoveAnchor) self.text.setTextCursor(cursor) def get_word_at(self, pos): """Returns the word at the given position. Args: pos: The position of the word. Returns: The word at the given position. """ text = self.text.toPlainText().strip().split() if pos < 0 or pos > len(text): return None return text[pos % len(text)] def set_word_at(self, word, pos, replace_old): """Sets the word at the given position. Args: word: The replacement. pos: The position. replace_old: If true, the old word at the position will be replaced, otherwise the word will be set before the old word. """ old_word = self.get_word_at(pos) cursor = self.text.textCursor() cursor_pos = cursor.position() if pos < 0: self.text.setPlainText(word + " " + self.text.toPlainText()) cursor.setPosition(cursor_pos, QTextCursor.MoveAnchor) self.text.setTextCursor(cursor) return text = self.text.toPlainText().strip().split() if replace_old and pos < len(text): if word: text[pos] = word else: text.pop(pos) else: text.insert(pos, word) text = " ".join(text) self.set_text_with_line_breaks(text) cursor_pos += len(word) if replace_old: cursor_pos -= len(old_word) if not word: cursor_pos -= 1 else: cursor_pos += 1 words_to_cursor_pos = self.text.toPlainText()[:cursor_pos].split() self.word_pos = len(words_to_cursor_pos) - 1 cursor.setPosition(cursor_pos, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor) self.text.setTextCursor(cursor) def find_line_breaks(self): """Returns the lien breaks in the text. Returns: The positions of the linebreaks """ found = [] start = 0 text = self.text.toPlainText() while True: start = text.find("\n", start) if start == -1: return found found.append(start) start += len("\n") def set_text_with_line_breaks(self, text): """Sets the text with linebreaks. Args: text: the new text. """ line_breaks = self.find_line_breaks() for n in line_breaks: text = text[:n + 1] + "\n" + text[n + 1:] text = text.replace(" \n", "\n") text = text.replace("\n ", "\n") self.text.setPlainText(text) def insert_time_stamp(self): """Inserts the current timestamp at the current cursor position.""" cursor = self.text.textCursor() time = "[" + convert_ms(self.media_player.position()) + "]" cursor.insertText(time) def start_hear_again(self, start_time, end_time): """Starts the audio for the specific word from the hear again button. Args: start_time: When to start the audio. end_time: When to end the audio. """ if self.media_player.state() == QMediaPlayer.PlayingState: return self.media_player.pause() self.word_start_time = start_time self.word_end_time = end_time self.media_player.setPosition(self.word_start_time) self.on_play()
class Player(QWidget): media_loaded = Signal(str) stopped = Signal(str) playlist_size_changed = Signal(int) handle_double_click = Slot() def __init__(self, parent=None): super(Player, self).__init__(parent) self.duration = 0 self.volume = 50 self.player = QMediaPlayer() self.playlist = Playlist(self) self.videoWidget = VideoWidget() self.next_url = QUrl() self.context_menu = QMenu(self) self.display_splitter = QSplitter(Qt.Horizontal) self.repeat_control = RepeatControl(parent=self) self.repeat_control.get_player_position = self.player.position self.repeat_control.set_position_to_player = self.player.setPosition self.player.positionChanged.connect(self.repeat_control.set_pos) self.setAcceptDrops(True) std_icon = self.style().standardIcon self.play_button = create_flat_button(std_icon(QStyle.SP_MediaPlay)) self.stopButton = create_flat_button(std_icon(QStyle.SP_MediaStop), '') self.backwardButton = create_flat_button( std_icon(QStyle.SP_MediaSkipBackward), '') self.forwardButton = create_flat_button( std_icon(QStyle.SP_MediaSkipForward), '') self.order_list = self.repeat_control.menu() self.order_list.setFixedWidth(115) self.playback_rate_menu = QComboBox() self.playback_rate_menu.addItems( ('0.5x', '0.75x', '0.9x', '1.0x', '1.1x', '1.25x', '1.5x')) self.playback_rate_menu.setCurrentText('1.0x') self.muteButton = create_flat_button( std_icon(QStyle.SP_MediaVolume if not self.player.isMuted() else QStyle.SP_MediaVolumeMuted)) self.volumeBar = QSlider(Qt.Horizontal) self.volumeBar.setRange(0, 100) self.volumeBar.setValue(self.volume) self.labelVolume = QLabel(str(self.volume)) self.labelVolume.setMinimumWidth(24) self.statusInfoLabel = QLabel() self.seekBar = QSlider(Qt.Horizontal) self.seekBar.setRange(0, self.player.duration() / 1000) self.labelTotalTime = QLabel('00:00') self.labelCurrentTime = QLabel('00:00') self.create_layout() self.create_connections() self.player.setVideoOutput(self.videoWidget) self.videoWidget.show() def create_layout(self): seekBarLayout = QHBoxLayout() seekBarLayout.addWidget(self.labelCurrentTime) seekBarLayout.addWidget(self.seekBar) seekBarLayout.addWidget(self.labelTotalTime) controlWithoutSeekBarLayout = QHBoxLayout() controlWithoutSeekBarLayout.setSpacing(1) controlWithoutSeekBarLayout.addWidget(self.play_button) controlWithoutSeekBarLayout.addWidget(self.stopButton) controlWithoutSeekBarLayout.addWidget(self.backwardButton) controlWithoutSeekBarLayout.addWidget(self.forwardButton) controlWithoutSeekBarLayout.addWidget(self.order_list) controlWithoutSeekBarLayout.addWidget(self.playback_rate_menu) controlWithoutSeekBarLayout.addStretch(stretch=2) controlWithoutSeekBarLayout.addWidget(self.muteButton) controlWithoutSeekBarLayout.addWidget(self.volumeBar) controlWithoutSeekBarLayout.addWidget(self.labelVolume, alignment=Qt.AlignRight) controlLayout = QVBoxLayout() controlLayout.addLayout(seekBarLayout) controlLayout.addLayout(controlWithoutSeekBarLayout) self.display_splitter.setOpaqueResize(False) self.display_splitter.addWidget(self.videoWidget) self.display_splitter.addWidget(self.playlist.widget) self.display_splitter.setSizes([300, 200]) layout = QVBoxLayout() layout.setContentsMargins(11, 0, 11, 0) layout.addWidget(self.display_splitter, 1) layout.addLayout(controlLayout) layout.addWidget(self.repeat_control.ab_repeat_widget) layout.addWidget(self.statusInfoLabel) self.setLayout(layout) def create_connections(self): self.play_button.clicked.connect(self.optimal_play) self.stopButton.clicked.connect(self.stop) self.backwardButton.clicked.connect(self.skip_backward) self.forwardButton.clicked.connect(self.skip_forward) self.muteButton.clicked.connect(self.toggleMute) self.playback_rate_menu.currentTextChanged.connect( self.set_playback_rate) self.player.stateChanged.connect(self.playerStateChanged) self.player.mediaStatusChanged.connect(self.mediaStatusChanged) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.error.connect(self.handleError) self.volumeBar.sliderMoved.connect(self.setVolume) self.volumeBar.sliderReleased.connect(self.setVolume) self.volumeBar.valueChanged.connect(self.volumeChanged) self.seekBar.sliderMoved.connect(self.seek) self.seekBar.sliderReleased.connect(self.seekBarClicked) self.repeat_control.pos_exceeded.connect(self.seek) self.player.currentMediaChanged.connect(self.repeat_control.reset) self.playlist.double_clicked.connect(self.load_and_play) self.videoWidget.double_clicked.connect(self.no_future) def contextMenuEvent(self, event): self.context_menu.exec_(event.globalPos()) def read_settings(self): settings = QSettings() settings.beginGroup('player') self.order_list.setCurrentIndex(settings.value('order_list', 0)) self.display_splitter.restoreState( QByteArray(settings.value('splitter_sizes'))) settings.endGroup() self.playlist.read_settings() def no_future(self): self.display_splitter.moveSplitter(0, 1) def autoplay(self): """メディアを読み込み、再生する。 order_listに応じて、次に何を再生するかを決める。 """ i = self.order_list.currentIndex() if i == 1: # self.repeat_track() return elif i == 2: self.repeat_all() else: self.next_track() self.play() def optimal_play(self): if self.player.state() == QMediaPlayer.StoppedState: self.load_and_play() else: self.play() def load_and_play(self): self.load(self.playlist.get_new_one()) self.play() def load(self, file_url: QUrl): if file_url is None: return None if file_url.isValid(): c = QMediaContent(file_url) self.player.setMedia(c) self.media_loaded.emit(self.playlist.current_title()) self.enableInterface() def play(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() return if self.player.mediaStatus() == QMediaPlayer.LoadingMedia or\ self.player.mediaStatus() == QMediaPlayer.StalledMedia: QTimer.singleShot(600, self.player.play) self.player.play() self.playlist.update_listview() def stop(self): if not self.player.state() == QMediaPlayer.StoppedState: self.seek(0) self.player.stop() self.setStatusInfo('Stopped') self.stopped.emit('') def playerStateChanged(self, state): if state == QMediaPlayer.PlayingState: self.play_button.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.play_button.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def durationChanged(self, duration): self.repeat_control.set_duration(duration) duration /= 1000 self.duration = duration totalTime = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60), (duration * 1000) % 1000) format = 'hh:mm:ss' if duration > 3600 else 'mm:ss' totalTimeStr = totalTime.toString(format) self.labelTotalTime.setText(totalTimeStr) self.seekBar.setMaximum(duration) def positionChanged(self, progress): progress /= 1000 self.updateCurrentTime(progress) self.seekBar.setValue(progress) def updateCurrentTime(self, currentInfo): if currentInfo: currentTime = QTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60, currentInfo % 60, (currentInfo * 1000) % 1000) format = 'hh:mm:ss' if self.duration > 3600 else 'mm:ss' currentTimeStr = currentTime.toString(format) else: currentTimeStr = '00:00' self.labelCurrentTime.setText(currentTimeStr) def repeat_track(self): QTimer.singleShot(50, self.play) def repeat_all(self): if self.playlist.count() - 1 == self.playlist.current_row(): url = self.playlist.first() self.load(url) else: self.next_track() def setVolume(self): self.player.setVolume(self.volumeBar.sliderPosition() * 2) def volumeChanged(self): self.labelVolume.setText(str(self.volumeBar.sliderPosition())) self.volume = self.volumeBar.sliderPosition() def seekBarClicked(self): self.seek(self.seekBar.sliderPosition()) def seek(self, seconds): self.player.setPosition(seconds * 1000) def set_playback_rate(self, rate_text): self.player.setPlaybackRate(float(rate_text[:-1])) def toggleMute(self): if self.player.isMuted(): self.player.setMuted(False) self.muteButton.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume)) else: self.player.setMuted(True) self.muteButton.setIcon(self.style().standardIcon( QStyle.SP_MediaVolumeMuted)) def disableInterface(self): self.play_button.setEnabled(False) self.stopButton.setEnabled(False) self.backwardButton.setEnabled(False) self.forwardButton.setEnabled(False) self.labelCurrentTime.setText('00:00') self.labelTotalTime.setText('00:00') def enableInterface(self): self.play_button.setEnabled(True) self.stopButton.setEnabled(True) self.backwardButton.setEnabled(True) self.forwardButton.setEnabled(True) def mediaStatusChanged(self, status): if status == QMediaPlayer.LoadingMedia: self.setStatusInfo('Loading...') elif status == QMediaPlayer.BufferingMedia: self.setStatusInfo('Buffering') elif status == QMediaPlayer.EndOfMedia: # self.player.stop() self.autoplay() elif status == QMediaPlayer.InvalidMedia: self.handleError() #TODO: Step Forward を割り当てる def clearStatusInfo(self): self.statusInfoLabel.setText("") def handleError(self): self.disableInterface() self.setStatusInfo('Error: ' + self.player.errorString()) def setStatusInfo(self, message, seconds=5): if not message == '': self.statusInfoLabel.setText(message) QTimer.singleShot(seconds * 1000, self.clearStatusInfo) def next_track(self): url = self.playlist.next() if url is None: return None else: self.load(url) def previous_track(self): url = self.playlist.previous() if url is None: return None else: self.load(url) def skip_forward(self): self.next_track() self.play() def skip_backward(self): if self.seekBar.sliderPosition() > 2: self.seek(0) else: self.previous_track() self.play() def forward(self, seconds): currentPosition = self.seekBar.sliderPosition() if currentPosition + seconds < self.duration: self.seek(currentPosition + seconds) else: self.seek(self.duration - 1) def backward(self, seconds): self.forward(-seconds) def forward_short(self): self.forward(SeekStep.SHORT) def forward_medium(self): self.forward(SeekStep.MEDIUM) def forward_long(self): self.forward(SeekStep.LONG) def forward_verylong(self): self.forward(SeekStep.VERYLONG) def backward_short(self): self.backward(SeekStep.SHORT) def backward_medium(self): self.backward(SeekStep.MEDIUM) def backward_long(self): self.backward(SeekStep.LONG) def backward_verylong(self): self.backward(SeekStep.VERYLONG) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() def dragMoveEvent(self, event): if event.mimeData().hasUrls(): event.accept() def dropEvent(self, event): if event.mimeData().hasUrls(): urls = event.mimeData().urls() self.load(urls[0]) # self.stop() self.play()
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(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.pBLecture.clicked.connect(self.lecture) self.ui.pBPause.clicked.connect(self.pause) self.ui.pBStop.clicked.connect(self.stop) self.ui.pBPrecedent.clicked.connect(self.precedent) self.ui.pBSuivant.clicked.connect(self.suivant) self.ui.pBAjout.clicked.connect(self.ajoutListe) self.ui.pBSupp.clicked.connect(self.suppListe) self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected) self.ui.dBVolume.valueChanged.connect(self.volume) self.ui.dBVolume.setRange(0, 100) self.ui.suiviVol.setText(f'{str(self.ui.dBVolume.value())} %') self.ui.sTpsCourant.valueChanged.connect(self.avanceSlider) self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.ui.Lecteur) self.mediaPlayer.durationChanged.connect(self.duree) self.mediaPlayer.positionChanged.connect(self.avancee) # mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi")) # self.mediaPlayer.setMedia(mediaContent) def lecture(self): print("Lecture") if self.mediaPlayer.state() == QMediaPlayer.StoppedState: self.mediaSelected() else: self.mediaPlayer.play() def pause(self): print("Pause") if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def stop(self): print("Stop") self.mediaPlayer.stop() def precedent(self): currentItemRow = self.ui.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.ui.listWidget.count() self.ui.listWidget.setCurrentRow((currentItemRow - 1) % totalItems) self.mediaSelected() print("Précédent") def suivant(self): currentItemRow = self.ui.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.ui.listWidget.count() self.ui.listWidget.setCurrentRow((currentItemRow + 1) % totalItems) self.mediaSelected() print("Suivant") # def ajoutListe (self): # print("Ajout dans playlist") # newFile=QFileDialog.getOpenFileName(self, "Choix Film", "/home", "Movie Files (*.avi, *.mp4)") # newMovie=QListWidgetItem(newFile[0]) # self.ui.listWidget.addItem(newMovie) def ajoutListe(self): print("Ajout dans playlist") newFile = QFileDialog.getOpenFileName(self, "Choix Film", "/home", "Movie Files (*.avi, *.mp4)") fInfo = QFileInfo(newFile[0]) fShortName = fInfo.baseName() newMovie = QListWidgetItem(fShortName) newMovie.setToolTip(newFile[0]) self.ui.listWidget.addItem(newMovie) def suppListe(self): print("Supprimer de playList") rowItem = self.ui.listWidget.currentRow() if rowItem != -1: self.ui.listWidget.takeItem(rowItem) # def mediaSelected (self): # currentItem = self.ui.listWidget.currentItem() # mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text())) # self.mediaPlayer.setMedia(mediaContent) # self.lecture() def mediaSelected(self): currentItem = self.ui.listWidget.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip())) self.mediaPlayer.setMedia(mediaContent) self.mediaPlayer.play() def volume(self): self.mediaPlayer.setVolume(self.ui.dBVolume.value()) self.ui.suiviVol.setText(f'{str(self.ui.dBVolume.value())} %') def duree(self): mediaDuration = self.mediaPlayer.duration() self.ui.sTpsCourant.setRange(0, mediaDuration) totalTimeMedia = QTime(0, 0, 0) totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration) self.ui.lRestantTps.setText(totalTimeMedia.toString("HH:mm:ss")) def avancee(self): self.ui.sTpsCourant.valueChanged.disconnect(self.avanceSlider) mediaPosition = self.mediaPlayer.position() currentTimeMedia = QTime(0, 0, 0) currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition) self.ui.lAvanceeTps.setText(currentTimeMedia.toString("HH:mm:ss")) self.ui.sTpsCourant.setValue(mediaPosition) self.ui.sTpsCourant.valueChanged.connect(self.avanceSlider) def avanceSlider(self): self.mediaPlayer.positionChanged.disconnect(self.avancee) self.mediaPlayer.setPosition(self.ui.sTpsCourant.sliderPosition()) self.mediaPlayer.positionChanged.connect(self.avancee)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.lecture.clicked.connect(self.lectureClicked) self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.ui.ecran) self.ui.pause.clicked.connect(self.pauseClicked) self.ui.suivant.clicked.connect(self.suivantClicked) self.ui.stop.clicked.connect(self.stopClicked) self.ui.precedent.clicked.connect(self.precedentClicked) self.ui.dialVol.valueChanged.connect(self.dVol) self.ui.slider.sliderMoved.connect(self.sliderMov) mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi")) self.mediaPlayer.setMedia(mediaContent) self.mediaPlayer.positionChanged.connect(self.mediaDurationChange) self.mediaPlayer.positionChanged.connect(self.mediapositionChange) def lectureClicked(self): print("Lecture !!!") self.mediaPlayer.play() #self.sliderMov.connect() def pauseClicked(self): print("Pause !!!") if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def stopClicked(self): print("----------------stooooooop-----------------!") self.mediaPlayer.stop() def precedentClicked(self): print("Précédent !") def suivantClicked(self): print("Suivant !") def sliderMov(self): print("Slide .....") self.mediaPlayer.setPosition(self.ui.slider.value()) def onceu(self): ttalTimeMedia = self.mediaPlayer.duration() def mediaDurationChange(self): print("medialoaded") mediaDuration = self.mediaPlayer.duration() ttalTimeMedia = QTime(0, 0, 0) ttalTimeMedia = ttalTimeMedia.addMSecs(mediaDuration) self.ui.toBe.setText(ttalTimeMedia.toString("HH:mm:ss")) #self.ui.slider.setValue(mediaPosition) def mediapositionChange(self): mediaPosition = self.mediaPlayer.position() currentTimeMedia = QTime(0, 0, 0) currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition) self.ui.onceU.setText(currentTimeMedia.toString("HH:mm:ss")) self.ui.slider.setRange(0, self.mediaPlayer.duration()) self.ui.slider.setValue(self.mediaPlayer.position()) def dVol(self): self.ui.pourcent.setText(str(self.ui.dialVol.value()) + "%") self.mediaPlayer.setVolume(self.ui.dialVol.value())
class VideoWindow(QMainWindow): def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle( "PyQt Video Player Widget Example - pythonprogramminglanguage.com") self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create new action openAction = QAction(QIcon('open.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.triggered.connect(self.openFile) # Create exit action exitAction = QAction(QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # Create menu bar and add action menuBar = self.menuBar() fileMenu = menuBar.addMenu('&File') #fileMenu.addAction(newAction) fileMenu.addAction(openAction) fileMenu.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def exitCall(self): sys.exit(app.exec_()) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
class SoundPlayer: def __init__(self, soundfile, parent): self.soundfile = soundfile self.isplaying = False self.time = 0 # current audio position in frames self.audio = QMediaPlayer() self.decoder = QAudioDecoder() self.is_loaded = False self.volume = 100 self.isplaying = False self.decoded_audio = {} self.only_samples = [] self.decoding_is_finished = False self.max_bits = 32768 # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works self.audio.durationChanged.connect(self.on_durationChanged) #self.decoder.finished.connect(self.decode_finished_signal) self.audio.setMedia(QUrl.fromLocalFile(soundfile)) #self.decoder.setSourceFilename(soundfile) # strangely inconsistent file-handling # It will hang here forever if we don't process the events. while not self.is_loaded: QCoreApplication.processEvents() time.sleep(0.1) #self.decode_audio() #self.np_data = np.array(self.only_samples) #self.np_data = np.abs(self.np_data / self.max_bits) # A simple normalisation, with this the samples should all be between 0 and 1 # for i in self.decoded_audio.items(): # self.only_samples.extend(i[1][0]) # t = [] # for i in self.only_samples: # if i != []: # t.append(i + -(min(self.only_samples))) # # t2 = [] # for i in t: # t2.append(i / max(t)) # self.only_samples = t2 #print(len(self.only_samples)) #print(self.max_bits) self.isvalid = True self.pydubfile = None if AudioSegment: if which("ffmpeg") is not None: AudioSegment.converter = which("ffmpeg") elif which("avconv") is not None: AudioSegment.converter = which("avconv") else: if platform.system() == "Windows": AudioSegment.converter = os.path.join(get_main_dir(), "ffmpeg.exe") #AudioSegment.converter = os.path.dirname(os.path.realpath(__file__)) + "\\ffmpeg.exe" else: # TODO: Check if we have ffmpeg or avconv installed AudioSegment.converter = "ffmpeg" try: if AudioSegment: print(self.soundfile) self.pydubfile = AudioSegment.from_file(self.soundfile, format=os.path.splitext(self.soundfile)[1][1:]) else: self.wave_reference = wave.open(self.soundfile) self.isvalid = True except: traceback.print_exc() self.wave_reference = None self.isvalid = False #self.audio.play() def audioformat_to_datatype(self, audioformat): num_bits = audioformat.sampleSize() signed = audioformat.sampleType() self.max_bits = 2 ** int(num_bits) if signed == QAudioFormat.SampleType.UnSignedInt: return "uint" + str(num_bits) + "_t" elif signed == QAudioFormat.SampleType.SignedInt: self.max_bits = int(self.max_bits / 2) return "int" + str(num_bits) + "_t" def decode_audio(self): self.decoder.start() while not self.decoding_is_finished: QCoreApplication.processEvents() if self.decoder.bufferAvailable(): tempdata = self.decoder.read() # We use the Pointer Address to get a cffi Pointer to the data (hopefully) cast_data = self.audioformat_to_datatype(tempdata.format()) possible_data = ffi.cast("{1}[{0}]".format(tempdata.sampleCount(), cast_data), int(tempdata.constData())) current_sample_data = [] for i in possible_data: current_sample_data.append(int(ffi.cast(cast_data, i))) #x = int(ffi.cast("int16_t", possible_data[0])) self.only_samples.extend(current_sample_data) self.decoded_audio[self.decoder.position()] = [current_sample_data, len(possible_data), tempdata.byteCount(), tempdata.format()] def decode_finished_signal(self): self.decoding_is_finished = True def on_durationChanged(self, duration): print("Changed!") print(duration) self.is_loaded = True def get_audio_buffer(self, bufferdata): print(bufferdata) def IsValid(self): return self.isvalid def Duration(self): return self.audio.duration() / 1000.0 def GetRMSAmplitude(self, time, sampleDur): if AudioSegment: return self.pydubfile[time*1000.0:(time+sampleDur)*1000.0].rms else: startframe = int(round(time * self.wave_reference.getframerate())) samplelen = int(round(sampleDur * self.wave_reference.getframerate())) self.wave_reference.setpos(startframe) frame = self.wave_reference.readframes(samplelen) width = self.wave_reference.getsampwidth() return audioop.rms(frame, width) def is_playing(self): if self.audio.state() == QMediaPlayer.PlayingState: return True else: return False def set_cur_time(self, newtime): self.time = newtime * 1000.0 self.audio.setPosition(self.time) def stop(self): self.isplaying = False self.audio.stop() def current_time(self): self.time = self.audio.position() / 1000.0 return self.time def set_volume(self, newvolume): self.volume = newvolume self.audio.setVolume(self.volume) def play(self, arg): self.isplaying = True # TODO: We should be able to replace isplaying with queries to self.audio.state() self.audio.play() def play_segment(self, start, length): print("Playing Segment") if not self.isplaying: # otherwise this get's kinda echo-y self.isplaying = True self.audio.setPosition(start * 1000.0) self.audio.play() thread.start_new_thread(self._wait_for_segment_end, (start, length)) def _wait_for_segment_end(self, newstart, newlength): start = newstart * 1000.0 length = newlength * 1000.0 end = start + length print(start) print(length) print(end) while self.audio.position() < end: QCoreApplication.processEvents() print(self.audio.position()) time.sleep(0.001) self.audio.stop() self.isplaying = False
class Form(QMainWindow): def __init__(self, parent=None): super(Form, self).__init__(parent) self.setObjectName("MainWindow") self.resize(804, 559) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.centralwidget) self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.wVideo = QVideoWidget(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.wVideo.sizePolicy().hasHeightForWidth()) self.wVideo.setSizePolicy(sizePolicy) self.wVideo.setObjectName("wVideo") self.verticalLayout.addWidget(self.wVideo) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.lStartTime = QtWidgets.QLabel(self.centralwidget) self.lStartTime.setObjectName("lStartTime") self.horizontalLayout_2.addWidget(self.lStartTime) self.sProgression = QtWidgets.QSlider(self.centralwidget) self.sProgression.setOrientation(QtCore.Qt.Horizontal) self.sProgression.setObjectName("sProgression") self.horizontalLayout_2.addWidget(self.sProgression) self.lEndTime = QtWidgets.QLabel(self.centralwidget) self.lEndTime.setObjectName("lEndTime") self.horizontalLayout_2.addWidget(self.lEndTime) self.verticalLayout.addLayout(self.horizontalLayout_2) self.lBoutons = QtWidgets.QHBoxLayout() self.lBoutons.setObjectName("lBoutons") self.pbLecture = QtWidgets.QPushButton(self.centralwidget) self.pbLecture.setObjectName("pbLecture") self.lBoutons.addWidget(self.pbLecture) self.pbPause = QtWidgets.QPushButton(self.centralwidget) self.pbPause.setObjectName("pbPause") self.lBoutons.addWidget(self.pbPause) self.pbStop = QtWidgets.QPushButton(self.centralwidget) self.pbStop.setObjectName("pbStop") self.lBoutons.addWidget(self.pbStop) self.pbSuivant = QtWidgets.QPushButton(self.centralwidget) self.pbSuivant.setObjectName("pbSuivant") self.lBoutons.addWidget(self.pbSuivant) self.pbPrecedent = QtWidgets.QPushButton(self.centralwidget) self.pbPrecedent.setObjectName("pbPrecedent") self.lBoutons.addWidget(self.pbPrecedent) self.verticalLayout.addLayout(self.lBoutons) self.horizontalLayout.addLayout(self.verticalLayout) self.verticalLayout_3 = QtWidgets.QVBoxLayout() self.verticalLayout_3.setObjectName("verticalLayout_3") self.line = QtWidgets.QFrame(self.centralwidget) self.line.setBaseSize(QtCore.QSize(0, 0)) self.line.setFrameShape(QtWidgets.QFrame.VLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.verticalLayout_3.addWidget(self.line) spacerItem = QtWidgets.QSpacerItem(20, 100, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) self.verticalLayout_3.addItem(spacerItem) self.horizontalLayout.addLayout(self.verticalLayout_3) self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setObjectName("label_3") self.verticalLayout_2.addWidget(self.label_3) self.listWidget = QtWidgets.QListWidget(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.listWidget.sizePolicy().hasHeightForWidth()) self.listWidget.setSizePolicy(sizePolicy) self.listWidget.setObjectName("listWidget") self.verticalLayout_2.addWidget(self.listWidget) self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem1) self.pbAjout = QtWidgets.QPushButton(self.centralwidget) self.pbAjout.setObjectName("pbAjout") self.horizontalLayout_3.addWidget(self.pbAjout) self.pbSuppr = QtWidgets.QPushButton(self.centralwidget) self.pbSuppr.setObjectName("pbSuppr") self.horizontalLayout_3.addWidget(self.pbSuppr) self.verticalLayout_2.addLayout(self.horizontalLayout_3) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem2) self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setObjectName("label_4") self.horizontalLayout_4.addWidget(self.label_4) self.dVolume = QtWidgets.QDial(self.centralwidget) self.dVolume.setObjectName("dVolume") self.horizontalLayout_4.addWidget(self.dVolume) self.lPourcentVolume = QtWidgets.QLabel(self.centralwidget) self.lPourcentVolume.setObjectName("lPourcentVolume") self.horizontalLayout_4.addWidget(self.lPourcentVolume) self.verticalLayout_2.addLayout(self.horizontalLayout_4) self.horizontalLayout.addLayout(self.verticalLayout_2) self.horizontalLayout_5.addLayout(self.horizontalLayout) self.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(self) self.menubar.setGeometry(QtCore.QRect(0, 0, 804, 21)) self.menubar.setObjectName("menubar") self.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.retranslateUi(self) QtCore.QMetaObject.connectSlotsByName(self) self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.wVideo) self.pbLecture.clicked.connect(self.lectureClic) self.pbPause.clicked.connect(self.pauseClic) self.pbStop.clicked.connect(self.stopClic) self.pbSuivant.clicked.connect(self.suivantClic) self.pbPrecedent.clicked.connect(self.precedentClic) self.dVolume.valueChanged.connect(self.volumeChange) self.mediaPlayer.positionChanged.connect(self.progressionChange) self.sProgression.sliderMoved.connect(self.progressionDeplace) self.pbSuppr.clicked.connect(self.supprVid) self.pbAjout.clicked.connect(self.addVid) self.listWidget.itemDoubleClicked.connect(self.listeDoubleClic) self.dVolume.setMaximum(100) self.lEndTime.setText("") self.lStartTime.setText("") self.lPourcentVolume.setText("") self.dVolume.setValue(31) def progressionDeplace(self): self.mediaPlayer.setPosition(self.sProgression.value()) def progressionChange(self): self.lEndTime.setText(convertMillis(self.mediaPlayer.duration())) self.lStartTime.setText(str(convertMillis( self.mediaPlayer.position()))) self.sProgression.setRange(0, self.mediaPlayer.duration()) self.sProgression.setValue(self.mediaPlayer.position()) def lectureClic(self): mediaContent = QMediaContent(QUrl.fromLocalFile(self.openFile[0])) self.mediaPlayer.setMedia(mediaContent) self.mediaPlayer.play() def pauseClic(self): print("Pause") if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def stopClic(self): self.mediaPlayer.stop() def suivantClic(self): currentItemRow = self.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.listWidget.count() self.listWidget.setCurrentRow((currentItemRow + 1) % totalItems) self.listeDoubleClic() def precedentClic(self): currentItemRow = self.listWidget.currentRow() if currentItemRow == -1: return totalItems = self.listWidget.count() self.listWidget.setCurrentRow((currentItemRow - 1) % totalItems) self.listeDoubleClic() def volumeChange(self): self.lPourcentVolume.setText(str(self.dVolume.value())) self.mediaPlayer.setVolume(self.dVolume.value()) def supprVid(self): if self.listWidget.currentRow() != -1: self.listWidget.takeItem(self.listWidget.currentRow()) def addVid(self): self.openFile = QFileDialog.getOpenFileName( self, "Ouvrir...", ".", "Image Files (*.avi *.mp4)") self.listWidget.addItem(self.openFile[0]) def listeDoubleClic(self): self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile(self.listWidget.currentItem().text()))) self.mediaPlayer.play() def retranslateUi(self, MainWindow): self.setWindowTitle( QtWidgets.QApplication.translate("MainWindow", "MainWindow", None, -1)) self.lStartTime.setText( QtWidgets.QApplication.translate("MainWindow", "$start_time", None, -1)) self.lEndTime.setText( QtWidgets.QApplication.translate("MainWindow", "$end_time", None, -1)) self.pbLecture.setText( QtWidgets.QApplication.translate("MainWindow", "Lecture", None, -1)) self.pbPause.setText( QtWidgets.QApplication.translate("MainWindow", "Pause", None, -1)) self.pbStop.setText( QtWidgets.QApplication.translate("MainWindow", "Stop", None, -1)) self.pbSuivant.setText( QtWidgets.QApplication.translate("MainWindow", "Suivant", None, -1)) self.pbPrecedent.setText( QtWidgets.QApplication.translate("MainWindow", "Précédent", None, -1)) self.label_3.setText( QtWidgets.QApplication.translate("MainWindow", "Liste de lecture :", None, -1)) self.pbAjout.setText( QtWidgets.QApplication.translate("MainWindow", "+", None, -1)) self.pbSuppr.setText( QtWidgets.QApplication.translate("MainWindow", "-", None, -1)) self.label_4.setText( QtWidgets.QApplication.translate("MainWindow", "Volume :", None, -1)) self.lPourcentVolume.setText( QtWidgets.QApplication.translate("MainWindow", "$volume", None, -1))
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()
class MainWindow(QMainWindow): """ Description ------------- The central window that is responsible for the user-interface for the Trivial Purfuit application """ def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.number_players = 0 self.board = Board() self.start_menu = StartMenu() self.setup_menu = SetupMenu() self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.connect(self.start_menu.ui.new_game_button, SIGNAL("clicked()"), self.setup_game) self.connect(self.start_menu.ui.cancel_button, SIGNAL("clicked()"), self.close_game) self.connect(self.setup_menu.ui.start_game_button, SIGNAL("clicked()"), self.start_game) self.connect(self.setup_menu.ui.exit_game_button, SIGNAL("clicked()"), self.close_game) self.connect(self.board.restart_menu.ui.leave_game_button, SIGNAL("clicked()"), self.close_game) self.connect(self.board.restart_menu.ui.play_again_button, SIGNAL("clicked()"), self.restart_game) self.start_menu.show() #self.music_thread = Thread(target=self.play_background_music) #self.music_thread.start() # end __init__() def play_background_music(self): self.media_player.setMedia( QUrl.fromLocalFile( definitions.ROOT_DIR + "/Trivial_Purfuit/resources/audio/bensound-anewbeginning.mp3")) self.media_player.setVolume(5) self.media_player.play() while True: print("State: ", self.media_player.state()) # end play_background_music def setup_game(self): """ Description ------------- - Function to configure/setup a new game """ self.start_menu.hide() self.setup_menu.show() # end setup_game() def start_game(self): """ Description ------------- - Function to start the game """ try: self.number_players = int( self.setup_menu.ui.players_text_edit.toPlainText()) pone_name = self.setup_menu.ui.playerOneNameTextEdit.toPlainText() ptwo_name = self.setup_menu.ui.playerTwoNameTextEdit.toPlainText() pthree_name = self.setup_menu.ui.playerThreeNameTextEdit.toPlainText( ) pfour_name = self.setup_menu.ui.playerFourNameTextEdit.toPlainText( ) self.board.initialize_player_tokens(self.number_players, pone_name, ptwo_name, pthree_name, pfour_name) self.setup_menu.hide() self.board.initialize_game() self.board.show() self.board.hide_dirs() # TODO: JGC self.board.board_menu.ui.player_order_group_box.hide() except ValueError: print("[ERROR] Invalid input! Must be (1, 2, 3, or 4)!") # end start_game() def close_game(self): """ Description ------------- - Terminate the Trivial Purfuit application """ #self.music_thread.join() QApplication.quit() # end close_game() def restart_game(self): self.board = Board() self.connect(self.board.restart_menu.ui.leave_game_button, SIGNAL("clicked()"), self.close_game) self.connect(self.board.restart_menu.ui.play_again_button, SIGNAL("clicked()"), self.restart_game) self.setup_menu.show()
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setFixedSize(400, 100) self.setWindowTitle("PyPRad") # Icon made by https://www.flaticon.com/authors/freepik self.setWindowIcon(QIcon("icon.png")) self.setWindowIconText("PyPRad") self.current_stream = "https://kathy.torontocast.com:3060/stream" # Add a Stream URL. Default URL # Setup Media Player self.player = QMediaPlayer(self, QMediaPlayer.StreamPlayback) self.player.setMedia(QUrl(self.current_stream)) # Connect Button connect_btn = QPushButton("Connect To Stream") connect_btn.setFixedWidth(150) connect_btn.clicked.connect(self.connectStream) # Play Button self.play = QPushButton() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.play.setFixedWidth(100) self.play.clicked.connect(self.playStream) # Volume Slider slider = QSlider(Qt.Horizontal) slider.setRange(0, 100) slider.setFixedWidth(100) slider.setValue(100) slider.valueChanged.connect(self.setVolume) # Horizontal Layout hbox_layout = QHBoxLayout() hbox_layout.setContentsMargins(0, 0, 0, 0) hbox_layout.addWidget(connect_btn) hbox_layout.addWidget(self.play) hbox_layout.addWidget(slider) widget = QWidget() widget.setLayout(hbox_layout) self.player.stateChanged.connect(self.mediaStateChanged) self.setCentralWidget(widget) def connectStream(self): dlg = QInputDialog(self) dlg.setInputMode(QInputDialog.TextInput) dlg.setLabelText("URL:") dlg.setTextEchoMode(QLineEdit.Normal) dlg.setTextValue(self.current_stream) dlg.resize(400, 100) dlg.exec() if dlg.result() and validators.url( dlg.textValue()) and dlg.textValue() != self.current_stream: self.current_stream = dlg.textValue() self.player.setMedia(QUrl(self.current_stream)) elif dlg.result() and not validators.url(dlg.textValue()): msg_box = QMessageBox() msg_box.setText("Error URL. Please try again") msg_box.setWindowTitle("Error URL") msg_box.exec() self.connectStream() def playStream(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() else: self.player.play() def mediaStateChanged(self, state): if self.player.state() == QMediaPlayer.PlayingState: self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) else: self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) def setVolume(self, volume): self.player.setVolume(volume)
class VideoPlayer(QWidget): def __init__(self, aPath, parent=None): super(VideoPlayer, self).__init__(parent) self.setAttribute(Qt.WA_NoSystemBackground, True) self.setAcceptDrops(True) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback) self.mediaPlayer.mediaStatusChanged.connect(self.printMediaData) self.mediaPlayer.setVolume(80) self.videoWidget = QVideoWidget(self) self.lbl = QLineEdit('00:00:00') self.lbl.setReadOnly(True) self.lbl.setFixedWidth(70) self.lbl.setUpdatesEnabled(True) self.lbl.setStyleSheet(stylesheet(self)) self.lbl.selectionChanged.connect(lambda: self.lbl.setSelection(0, 0)) self.elbl = QLineEdit('00:00:00') self.elbl.setReadOnly(True) self.elbl.setFixedWidth(70) self.elbl.setUpdatesEnabled(True) self.elbl.setStyleSheet(stylesheet(self)) self.elbl.selectionChanged.connect( lambda: self.elbl.setSelection(0, 0)) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setFixedWidth(32) self.playButton.setStyleSheet("background-color: black") self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal, self) self.positionSlider.setStyleSheet(stylesheet(self)) self.positionSlider.setRange(0, 100) self.positionSlider.sliderMoved.connect(self.setPosition) self.positionSlider.setSingleStep(2) self.positionSlider.setPageStep(20) self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True) self.clip = QApplication.clipboard() self.process = QProcess(self) self.process.readyRead.connect(self.dataReady) self.process.finished.connect(self.playFromURL) self.myurl = "" controlLayout = QHBoxLayout() controlLayout.setContentsMargins(5, 0, 5, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.lbl) controlLayout.addWidget(self.positionSlider) controlLayout.addWidget(self.elbl) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.videoWidget) layout.addLayout(controlLayout) self.setLayout(layout) self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \ "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \ "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes" self.widescreen = True #### shortcuts #### self.shortcut = QShortcut(QKeySequence("q"), self) self.shortcut.activated.connect(self.handleQuit) self.shortcut = QShortcut(QKeySequence("u"), self) self.shortcut.activated.connect(self.playFromURL) self.shortcut = QShortcut(QKeySequence("y"), self) self.shortcut.activated.connect(self.getYTUrl) self.shortcut = QShortcut(QKeySequence("o"), self) self.shortcut.activated.connect(self.openFile) self.shortcut = QShortcut(QKeySequence(" "), self) self.shortcut.activated.connect(self.play) self.shortcut = QShortcut(QKeySequence("f"), self) self.shortcut.activated.connect(self.handleFullscreen) self.shortcut = QShortcut(QKeySequence("i"), self) self.shortcut.activated.connect(self.handleInfo) self.shortcut = QShortcut(QKeySequence("s"), self) self.shortcut.activated.connect(self.toggleSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self) self.shortcut.activated.connect(self.volumeUp) self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self) self.shortcut.activated.connect(self.volumeDown) self.shortcut = QShortcut( QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider10) self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider10) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) print("QT5 Player started") print("press 'o' to open file (see context menu for more)") self.suspend_screensaver() def mouseDoubleClickEvent(self, event): self.handleFullscreen() def playFromURL(self): self.mediaPlayer.pause() self.myurl = self.clip.text() self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl))) self.playButton.setEnabled(True) self.mediaPlayer.play() self.hideSlider() print(self.myurl) def getYTUrl(self): cmd = "youtube-dl -g -f best " + self.clip.text() print("grabbing YouTube URL") self.process.start(cmd) def dataReady(self): self.myurl = str(self.process.readAll(), encoding='utf8').rstrip() ### self.myurl = self.myurl.partition("\n")[0] print(self.myurl) self.clip.setText(self.myurl) self.playFromURL() def suspend_screensaver(self): 'suspend linux screensaver' proc = subprocess.Popen( 'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false', shell=True) proc.wait() def resume_screensaver(self): 'resume linux screensaver' proc = subprocess.Popen( 'gsettings set org.gnome.desktop.screensaver idle-activation-enabled true', shell=True) proc.wait() def openFile(self): fileName, _ = QFileDialog.getOpenFileName( self, "Open Movie", QDir.homePath() + "/Videos", "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)" ) if fileName != '': self.loadFilm(fileName) print("File loaded") def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) mtime = QTime(0, 0, 0, 0) mtime = mtime.addMSecs(self.mediaPlayer.position()) self.lbl.setText(mtime.toString()) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) mtime = QTime(0, 0, 0, 0) mtime = mtime.addMSecs(self.mediaPlayer.duration()) self.elbl.setText(mtime.toString()) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) print("Error: ", self.mediaPlayer.errorString()) def handleQuit(self): self.mediaPlayer.stop() self.resume_screensaver() print("Goodbye ...") app.quit() def contextMenuRequested(self, point): menu = QMenu() actionFile = menu.addAction(QIcon.fromTheme("video-x-generic"), "open File (o)") actionclipboard = menu.addSeparator() actionURL = menu.addAction(QIcon.fromTheme("browser"), "URL from Clipboard (u)") actionclipboard = menu.addSeparator() actionYTurl = menu.addAction(QIcon.fromTheme("youtube"), "URL from YouTube (y)") actionclipboard = menu.addSeparator() actionToggle = menu.addAction(QIcon.fromTheme("next"), "show / hide Slider (s)") actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"), "Fullscreen (f)") action169 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "16 : 9") action43 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "4 : 3") actionSep = menu.addSeparator() actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "Info (i)") action5 = menu.addSeparator() actionQuit = menu.addAction(QIcon.fromTheme("application-exit"), "Exit (q)") actionFile.triggered.connect(self.openFile) actionQuit.triggered.connect(self.handleQuit) actionFull.triggered.connect(self.handleFullscreen) actionInfo.triggered.connect(self.handleInfo) actionToggle.triggered.connect(self.toggleSlider) actionURL.triggered.connect(self.playFromURL) actionYTurl.triggered.connect(self.getYTUrl) action169.triggered.connect(self.screen169) action43.triggered.connect(self.screen43) menu.exec_(self.mapToGlobal(point)) def wheelEvent(self, event): mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mscale = event.angleDelta().y() / 5 if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth + mscale, round((mwidth + mscale) / 1.778)) else: self.setGeometry(mleft, mtop, mwidth + mscale, round((mwidth + mscale) / 1.33)) #elif self.positionSlider.hasFocus(): # self.positionSlider.value = self.positionSlider.value + 5 def screen169(self): self.widescreen = True mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mratio = 1.778 self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio)) def screen43(self): self.widescreen = False mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mratio = 1.33 self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio)) def handleFullscreen(self): if self.windowState() & Qt.WindowFullScreen: QApplication.setOverrideCursor(Qt.ArrowCursor) self.showNormal() print("no Fullscreen") else: self.showFullScreen() QApplication.setOverrideCursor(Qt.BlankCursor) print("Fullscreen entered") def handleInfo(self): msg = QMessageBox.about(self, "QT5 Player", self.myinfo) def toggleSlider(self): if self.positionSlider.isVisible(): self.hideSlider() else: self.showSlider() def hideSlider(self): self.playButton.hide() self.lbl.hide() self.positionSlider.hide() self.elbl.hide() mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.778)) else: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33)) def showSlider(self): self.playButton.show() self.lbl.show() self.positionSlider.show() self.elbl.show() mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.55)) else: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33)) def forwardSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60) def forwardSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60) def backSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60) def backSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60) def volumeUp(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10) print("Volume: " + str(self.mediaPlayer.volume())) def volumeDown(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10) print("Volume: " + str(self.mediaPlayer.volume())) def mousePressEvent(self, evt): self.oldPos = evt.globalPos() def mouseMoveEvent(self, evt): delta = QPoint(evt.globalPos() - self.oldPos) self.move(self.x() + delta.x(), self.y() + delta.y()) self.oldPos = evt.globalPos() def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() elif event.mimeData().hasText(): event.accept() else: event.ignore() def dropEvent(self, event): print("drop") if event.mimeData().hasUrls(): url = event.mimeData().urls()[0].toString() print("url = ", url) self.mediaPlayer.stop() self.mediaPlayer.setMedia(QMediaContent(QUrl(url))) self.playButton.setEnabled(True) self.mediaPlayer.play() elif event.mimeData().hasText(): mydrop = event.mimeData().text() ### YouTube url if "youtube" in mydrop: print("is YouTube", mydrop) self.clip.setText(mydrop) self.getYTUrl() else: ### normal url print("generic url = ", mydrop) self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop))) self.playButton.setEnabled(True) self.mediaPlayer.play() self.hideSlider() def loadFilm(self, f): self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f))) self.playButton.setEnabled(True) self.mediaPlayer.play() def printMediaData(self): if self.mediaPlayer.mediaStatus() == 6: if self.mediaPlayer.isMetaDataAvailable(): res = str(self.mediaPlayer.metaData("Resolution")).partition( "PyQt5.QtCore.QSize(")[2].replace(", ", "x").replace(")", "") print("%s%s" % ("Video Resolution = ", res)) if int(res.partition("x")[0]) / int( res.partition("x")[2]) < 1.5: self.screen43() else: self.screen169() else: print("no metaData available") def openFileAtStart(self, filelist): matching = [s for s in filelist if ".myformat" in s] if len(matching) > 0: self.loadFilm(matching)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.pbPlay.clicked.connect(self.lectureClicked) self.ui.pbPause.clicked.connect(self.pauseClicked) self.ui.pbStop.clicked.connect(self.stopClicked) self.ui.pbNext.clicked.connect(self.nextClicked) self.ui.pbPrevious.clicked.connect(self.previousClicked) self.ui.pbAdd.clicked.connect(self.addClicked) self.ui.pbDelete.clicked.connect(self.deleteClicked) self.ui.dVolume.valueChanged.connect(self.volume) self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.ui.wLecteur) self.mediaPlayer.durationChanged.connect(self.mediaDurationCnahged) self.mediaPlayer.positionChanged.connect(self.mediaPositionCnahged) self.ui.wList.itemDoubleClicked.connect(self.mediaSelected) mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi")) self.mediaPlayer.setMedia(mediaContent) def lectureClicked(self): print("Play") self.mediaPlayer.play() def pauseClicked(self): print("Pause") if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def stopClicked(self): print("Stop") self.mediaPlayer.stop() def nextClicked(self): print("Next") self.mediaPlayer.next() def previousClicked(self): print("Previous") self.mediaPlayer.previous() def volume(self): valeurVolume = self.ui.dVolume.value() self.mediaPlayer.setVolume(valeurVolume) self.ui.lPourcent.setText(str(valeurVolume) + "%") def mediaDurationCnahged(self): print("mediaLoaded") self.ui.lTemps.setText("00:00:00") #12 mediaDuration = self.mediaPlayer.duration( ) #donne le temps en milisecondes self.ui.sTimeLine.setRange(0, mediaDuration) #12 totalTimeMedia = QTime(0, 0, 0) totalTimeMedia = totalTimeMedia.addMSecs( mediaDuration) #convertir de milisecondes en H:m:s self.ui.lTempsTotal.setText(totalTimeMedia.toString("HH:mm:ss")) def mediaPositionCnahged(self): mediaPosition = self.mediaPlayer.position() self.ui.sTimeLine.setValue(mediaPosition) #12 currentTimeMedia = QTime(0, 0, 0) currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition) self.ui.lTemps.setText(currentTimeMedia.toString("HH:mm:ss")) def mediaSelected(self): currentItem = self.ui.wList.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile((currentItem.text()))) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def addClicked(self): print("+") nomMedia = QFileDialog.getOpenFileName( self, "Choix Film", "C:/Users/AELION/Desktop/Aelion/PyCharm/VideoProject", "Movie files (*.avi *.mp4)") # item = QListWidgetItem(nomMedia[0]) # self.ui.wList.addItem(item) fInfo = QFileInfo(nomMedia[0]) fShortName = fInfo.baseName() item = QListWidgetItem(fShortName) item.setToolTip(nomMedia[0]) self.ui.wList.addItem(item) def deleteClicked(self): print("-") rowItem = self.ui.wList.currentRow() if rowItem != -1: self.ui.wList.takeItem(rowItem)
class SoundPlayer: def __init__(self, soundfile, parent): self.soundfile = soundfile self.isplaying = False self.time = 0 # current audio position in frames self.audio = QMediaPlayer() self.decoder = QAudioDecoder() self.is_loaded = False self.volume = 100 self.isplaying = False self.decoded_audio = {} self.only_samples = [] self.decoding_is_finished = False self.max_bits = 32768 self.signed = False # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works self.audio.durationChanged.connect(self.on_durationChanged) self.decoder.finished.connect(self.decode_finished_signal) self.audio.setMedia(QUrl.fromLocalFile(soundfile)) self.decoder.setSourceFilename(soundfile) # strangely inconsistent file-handling # It will hang here forever if we don't process the events. while not self.is_loaded: QCoreApplication.processEvents() time.sleep(0.1) self.decode_audio() self.np_data = np.array(self.only_samples) if not self.signed: # don't ask me why this fixes 8 bit samples... self.np_data = self.np_data - self.max_bits / 2 print(len(self.only_samples)) print(self.max_bits) self.isvalid = True def audioformat_to_datatype(self, audioformat): num_bits = audioformat.sampleSize() signed = audioformat.sampleType() self.max_bits = 2 ** int(num_bits) if signed == QAudioFormat.SampleType.UnSignedInt: self.signed = False return "uint" + str(num_bits) + "_t" elif signed == QAudioFormat.SampleType.SignedInt: self.signed = True self.max_bits = int(self.max_bits / 2) return "int" + str(num_bits) + "_t" def decode_audio(self): self.decoder.start() while not self.decoding_is_finished: QCoreApplication.processEvents() if self.decoder.bufferAvailable(): tempdata = self.decoder.read() # We use the Pointer Address to get a cffi Pointer to the data (hopefully) cast_data = self.audioformat_to_datatype(tempdata.format()) possible_data = ffi.cast("{1}[{0}]".format(tempdata.sampleCount(), cast_data), int(tempdata.constData())) self.only_samples.extend(possible_data) self.decoded_audio[self.decoder.position()] = [possible_data, len(possible_data), tempdata.byteCount(), tempdata.format()] def decode_finished_signal(self): self.decoding_is_finished = True def on_durationChanged(self, duration): print("Changed!") print(duration) self.is_loaded = True def get_audio_buffer(self, bufferdata): print(bufferdata) def IsValid(self): return self.isvalid def Duration(self): return self.audio.duration() / 1000.0 def GetRMSAmplitude(self, time, sampleDur): # time_start = time * (len(self.only_samples)/self.Duration()) # time_end = (time + sampleDur) * (len(self.only_samples)/self.Duration()) # samples = self.only_samples[int(time_start):int(time_end)] time_start = time * (len(self.np_data) / self.Duration()) time_end = (time + sampleDur) * (len(self.np_data) / self.Duration()) samples = self.np_data[int(time_start):int(time_end)] if len(samples): return np.sqrt(np.mean(samples ** 2)) else: return 1 def is_playing(self): if self.audio.state() == QMediaPlayer.PlayingState: return True else: return False def set_cur_time(self, newtime): self.time = newtime * 1000.0 self.audio.setPosition(self.time) def stop(self): self.isplaying = False self.audio.stop() def current_time(self): self.time = self.audio.position() / 1000.0 return self.time def set_volume(self, newvolume): self.volume = newvolume self.audio.setVolume(self.volume) def play(self, arg): self.isplaying = True # TODO: We should be able to replace isplaying with queries to self.audio.state() self.audio.play() def play_segment(self, start, length): print("Playing Segment") if not self.is_playing(): # otherwise this get's kinda echo-y self.isplaying = True self.audio.setPosition(start * 1000.0) self.audio.play() thread.start_new_thread(self._wait_for_segment_end, (start, length)) def _wait_for_segment_end(self, newstart, newlength): start = newstart * 1000.0 length = newlength * 1000.0 end = start + length print(start) print(length) print(end) while self.audio.position() < end: if not self.isplaying: return 0 QCoreApplication.processEvents() print(self.audio.position()) time.sleep(0.001) self.audio.stop() self.isplaying = False
class SoundPlayer: def __init__(self, soundfile, parent): self.soundfile = soundfile self.isplaying = False self.time = 0 # current audio position in frames self.audio = QMediaPlayer() self.is_loaded = False self.volume = 100 self.isplaying = False self.max_bits = 32768 # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works self.audio.durationChanged.connect(self.on_durationChanged) # self.decoder.finished.connect(self.decode_finished_signal) self.audio.setMedia(QUrl.fromLocalFile(soundfile)) # self.decoder.setSourceFilename(soundfile) # strangely inconsistent file-handling # It will hang here forever if we don't process the events. self.audio_file = audioread.audio_open(self.soundfile) self.audio_data = [] for buf in self.audio_file: self.audio_data.extend( struct.unpack("<{}H".format(int(len(list(buf)) / 2)), buf)) print(self.audio_data) print(len(self.audio_data)) print(len(self.audio_data) / self.audio_file.samplerate) print(self.audio_file.duration) print(self.audio_file.channels) print("DATAEND") while not self.is_loaded: QCoreApplication.processEvents() time.sleep(0.1) self.isvalid = True self.pydubfile = None if AudioSegment: if which("ffmpeg") is not None: AudioSegment.converter = which("ffmpeg") elif which("avconv") is not None: AudioSegment.converter = which("avconv") else: if platform.system() == "Windows": AudioSegment.converter = os.path.join( get_main_dir(), "ffmpeg.exe") # AudioSegment.converter = os.path.dirname(os.path.realpath(__file__)) + "\\ffmpeg.exe" else: # TODO: Check if we have ffmpeg or avconv installed AudioSegment.converter = "ffmpeg" self.isvalid = True # self.audio.play() def on_durationChanged(self, duration): print("Changed!") print(duration) self.is_loaded = True def get_audio_buffer(self, bufferdata): print(bufferdata) def IsValid(self): return self.isvalid def Duration(self): return self.audio.duration() / 1000.0 def GetRMSAmplitude(self, time_pos, sample_dur): if AudioSegment: return self.pydubfile[time_pos * 1000.0:(time_pos + sample_dur) * 1000.0].rms else: if time_pos > 0: sample_pos = int(self.audio_file.samplerate * time_pos) else: sample_pos = 0 sample_end = int(sample_pos + sample_dur * self.audio_file.samplerate) return audioop.rms( struct.pack( "<{}H".format(len(self.audio_data[sample_pos:sample_end])), *self.audio_data[sample_pos:sample_end]), 2) def is_playing(self): if self.audio.state() == QMediaPlayer.PlayingState: return True else: return False def set_cur_time(self, newtime): self.time = newtime * 1000.0 self.audio.setPosition(self.time) def stop(self): self.isplaying = False self.audio.stop() def current_time(self): self.time = self.audio.position() / 1000.0 return self.time def set_volume(self, newvolume): self.volume = newvolume self.audio.setVolume(self.volume) def play(self, arg): self.isplaying = True # TODO: We should be able to replace isplaying with queries to self.audio.state() self.audio.play() def play_segment(self, start, length): print("Playing Segment") if not self.isplaying: # otherwise this get's kinda echo-y self.isplaying = True self.audio.setPosition(start * 1000.0) self.audio.play() thread.start_new_thread(self._wait_for_segment_end, (start, length)) def _wait_for_segment_end(self, newstart, newlength): start = newstart * 1000.0 length = newlength * 1000.0 end = start + length print(start) print(length) print(end) while self.audio.position() < end: if not self.isplaying: return 0 QCoreApplication.processEvents() print(self.audio.position()) time.sleep(0.001) self.audio.stop() self.isplaying = False
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.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.pbLecture.clicked.connect(self.lectureClicked) self.ui.pbPause.clicked.connect(self.pauseClicked) self.ui.pbStop.clicked.connect(self.stopClicked) self.ui.dVolume.valueChanged.connect(self.volumeChanged) self.ui.sTpsCourant.valueChanged.connect(self.sliderPositionChanged) self.ui.pbAjout.clicked.connect(self.ajouterMedia2) self.ui.pbSuppr.clicked.connect(self.supprMedia) self.ui.lPlaylist.itemDoubleClicked.connect(self.mediaSelected2) self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.ui.wVideo) self.mediaPlayer.durationChanged.connect(self.mediaDurationChanged) self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged) self.ui.pbSuivant.clicked.connect(self.suivantClicked) self.ui.pbPrecedent.clicked.connect(self.precedentClicked) def lectureClicked(self): print("Lecture !!") self.mediaPlayer.play() def pauseClicked(self): print("Pause !!") if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() elif self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() def stopClicked(self): self.mediaPlayer.stop() def volumeChanged(self): self.mediaPlayer.setVolume(self.ui.dVolume.value()) self.ui.lVolume.setText(str(self.ui.dVolume.value()) + "%") def mediaDurationChanged(self): print("mediaLoaded") self.ui.lTpsCourant.setText("00:00:00") mediaDuration = self.mediaPlayer.duration() self.ui.sTpsCourant.setRange(0, mediaDuration) ############### totalTimeMedia = QTime(0, 0, 0) totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration) self.ui.lTpsTotal.setText(totalTimeMedia.toString("HH:mm:ss")) def mediaPositionChanged(self): self.ui.sTpsCourant.valueChanged.disconnect(self.sliderPositionChanged) mediaPosition = self.mediaPlayer.position() self.ui.sTpsCourant.setValue(mediaPosition) ############## currentTimeMedia = QTime(0, 0, 0) currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition) self.ui.lTpsCourant.setText(currentTimeMedia.toString("HH:mm:ss")) self.ui.sTpsCourant.valueChanged.connect(self.sliderPositionChanged) def sliderPositionChanged(self): self.mediaPlayer.positionChanged.disconnect(self.mediaPositionChanged) self.mediaPlayer.setPosition(self.ui.sTpsCourant.value()) self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged) def ajouterMedia(self): nomMedia = QFileDialog.getOpenFileName(self, "Choix Film", "c:/", "Movie Files (*.avi *.mp4)") item = QListWidgetItem(nomMedia[0]) self.ui.lPlaylist.addItem(item) def ajouterMedia2(self): nomMedia = QFileDialog.getOpenFileName(self, "Choix Film", "c:/", "Movie Files (*.avi *.mp4)") if nomMedia[0] == "": #si aucun fichier selectionné return fInfo = QFileInfo(nomMedia[0]) fShortName = fInfo.baseName() item = QListWidgetItem(fShortName) item.setToolTip(nomMedia[0]) self.ui.lPlaylist.addItem(item) def supprMedia(self): rowItem = self.ui.lPlaylist.currentRow() if rowItem != -1: self.ui.lPlaylist.takeItem(rowItem) def mediaSelected(self): currentItem = self.ui.lPlaylist.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def mediaSelected2(self): currentItem = self.ui.lPlaylist.currentItem() mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip())) self.mediaPlayer.setMedia(mediaContent) self.lectureClicked() def suivantClicked(self): currentItemRow = self.ui.lPlaylist.currentRow() if currentItemRow == -1: return totalItems = self.ui.lPlaylist.count() self.ui.lPlaylist.setCurrentRow((currentItemRow + 1) % totalItems) self.mediaSelected2() def precedentClicked(self): currentItemRow = self.ui.lPlaylist.currentRow() if currentItemRow == -1: return totalItems = self.ui.lPlaylist.count() self.ui.lPlaylist.setCurrentRow((currentItemRow - 1) % totalItems) self.mediaSelected2()
class SoundPlayer: def __init__(self, soundfile, parent): self.soundfile = soundfile self.isplaying = False self.time = 0 # current audio position in frames self.audio = QMediaPlayer() self.decoder = QAudioDecoder() self.is_loaded = False self.volume = 100 self.isplaying = False self.decoded_audio = {} self.only_samples = [] self.decoding_is_finished = False self.max_bits = 32768 self.signed = False # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works self.audio.durationChanged.connect(self.on_durationChanged) self.decoder.finished.connect(self.decode_finished_signal) self.audio.setMedia(QUrl.fromLocalFile(soundfile)) self.decoder.setSourceFilename( soundfile) # strangely inconsistent file-handling self.top_level_widget = None for widget in QtWidgets.QApplication.topLevelWidgets(): if "lip_sync_frame" in dir(widget): self.top_level_widget = widget self.top_level_widget.lip_sync_frame.status_progress.show() self.top_level_widget.lip_sync_frame.status_progress.reset() self.top_level_widget.lip_sync_frame.status_progress.setMinimum(0) self.top_level_widget.lip_sync_frame.status_progress.setMaximum(0) # It will hang here forever if we don't process the events. while not self.is_loaded: QCoreApplication.processEvents() time.sleep(0.01) self.top_level_widget.lip_sync_frame.status_progress.setMaximum( self.decoder.duration()) self.decode_audio( self.top_level_widget.lip_sync_frame.status_bar_progress) self.top_level_widget.lip_sync_frame.status_progress.hide() self.np_data = np.array(self.only_samples) if not self.signed: # don't ask me why this fixes 8 bit samples... self.np_data = self.np_data - self.max_bits / 2 print(len(self.only_samples)) print(self.max_bits) self.isvalid = True def audioformat_to_datatype(self, audioformat): num_bits = audioformat.sampleSize() signed = audioformat.sampleType() self.max_bits = 2**int(num_bits) if signed == QAudioFormat.SampleType.UnSignedInt: self.signed = False return "uint{0}_t".format(str(num_bits)) elif signed == QAudioFormat.SampleType.SignedInt: self.signed = True self.max_bits = int(self.max_bits / 2) return "int{0}_t".format(str(num_bits)) def decode_audio(self, progress_callback): self.decoder.start() while not self.decoding_is_finished: QCoreApplication.processEvents() if self.decoder.bufferAvailable(): tempdata = self.decoder.read() # We use the Pointer Address to get a cffi Pointer to the data (hopefully) cast_data = self.audioformat_to_datatype(tempdata.format()) possible_data = ffi.cast( "{1}[{0}]".format(tempdata.sampleCount(), cast_data), int(tempdata.constData())) self.only_samples.extend(possible_data) self.decoded_audio[self.decoder.position()] = [ possible_data, len(possible_data), tempdata.byteCount(), tempdata.format() ] progress_callback(self.decoder.position()) def decode_finished_signal(self): self.decoding_is_finished = True def on_durationChanged(self, duration): self.is_loaded = True def get_audio_buffer(self, bufferdata): print(bufferdata) def IsValid(self): return self.isvalid def Duration(self): return self.audio.duration() / 1000.0 def GetRMSAmplitude(self, time_pos, sample_dur): # time_start = time_pos * (len(self.only_samples)/self.Duration()) # time_end = (time_pos + sample_dur) * (len(self.only_samples)/self.Duration()) # samples = self.only_samples[int(time_start):int(time_end)] time_start = time_pos * (len(self.np_data) / self.Duration()) time_end = (time_pos + sample_dur) * (len(self.np_data) / self.Duration()) samples = self.np_data[int(time_start):int(time_end)] if len(samples): return np.sqrt(np.mean(samples**2)) else: return 1 def is_playing(self): if self.audio.state() == QMediaPlayer.PlayingState: return True else: return False def set_cur_time(self, newtime): self.time = newtime * 1000.0 self.audio.setPosition(self.time) def stop(self): self.isplaying = False self.audio.stop() def current_time(self): self.time = self.audio.position() / 1000.0 return self.time def set_volume(self, newvolume): self.volume = newvolume self.audio.setVolume(self.volume) def play(self, arg): self.isplaying = True # TODO: We should be able to replace isplaying with queries to self.audio.state() self.audio.play() def play_segment(self, start, length): if not self.is_playing(): # otherwise this get's kinda echo-y self.isplaying = True self.audio.setPosition(start * 1000.0) self.audio.play() thread.start_new_thread(self._wait_for_segment_end, (start, length)) def _wait_for_segment_end(self, newstart, newlength): start = newstart * 1000.0 length = newlength * 1000.0 end = start + length while self.audio.position() < end: if not self.isplaying: return 0 QCoreApplication.processEvents() time.sleep(0.001) self.audio.stop() self.isplaying = False
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, parent=None): super(MainWindow, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.PLAY_Button.clicked.connect(self.PLAY) self.ui.PAUSE_Button.clicked.connect(self.PAUSE) self.ui.STOP_Button.clicked.connect(self.STOP) self.ui.PREV_Button.clicked.connect(self.PREV) self.ui.NEXT_Button.clicked.connect(self.NEXT) self.ui.next_file_button.clicked.connect(self.nextFile) self.ui.del_file_button.clicked.connect(self.delFile) self.ui.dial_volumen.setMinimum(0) self.ui.dial_volumen.setMaximum(100) self.ui.dial_volumen.setValue(3) self.ui.volumen_level.setText(str(self.ui.dial_volumen.value()) + '%') self.ui.sliderTime.setMinimum(0) self.ui.sliderTime.setMaximum(3600) self.ui.sliderTime.setValue(0) self.ui.timePlayed.setText(str(self.ui.sliderTime.value()) + 's') self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setVideoOutput(self.ui.wVideo) #mediaContent = QMediaContent(QUrl.fromLocalFile('big_buck_bunny.avi')) #self.mediaPlayer.setMedia(mediaContent) #Dialog self.ui.dial_volumen.valueChanged.connect(self.changeVolDial) self.mediaPlayer.positionChanged.connect(self.updateTime) self.ui.sliderTime.valueChanged.connect(self.changeTime) self.ui.file_list.itemDoubleClicked.connect(self.loadfile) def changeVolDial(self): print('VOLUMEN CHANGED') self.ui.volumen_level.setText(str(self.ui.dial_volumen.value()) + '%') self.mediaPlayer.setVolume(self.ui.dial_volumen.value()) def updateTime(self): self.ui.sliderTime.valueChanged.disconnect(self.changeTime) localTime = QTime(0, 0, 0) currentTime = localTime.addMSecs(self.mediaPlayer.position()) #print(self.mediaPlayer.position()-self.mediaPlayer.duration()) timeLeft = localTime.addMSecs(self.mediaPlayer.duration() - self.mediaPlayer.position()) #h, res = divmod(t, 3600) #m, s = divmod(res, 60) #time_str = f'{int(h):02}:{int(m):02}:{int(s):02}' self.ui.timePlayed.setText(currentTime.toString("HH:mm:ss")) self.ui.timeTotal.setText('-' + timeLeft.toString("HH:mm:ss")) self.ui.sliderTime.setValue(self.mediaPlayer.position()) self.ui.sliderTime.valueChanged.connect(self.changeTime) def loadfile(self): #rowItem=self.ui.file_list.currentRow() currentItem = self.ui.file_list.currentItem() print(self.ui.file_list.currentItem().text()) #mediaContent=QMediaContent(QUrl.fromLocalFile(currentItem.toolTip())) mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text())) #mediaContent = QMediaContent(QUrl.fromLocalFile('big_buck_bunny.avi')) self.mediaPlayer.setMedia(mediaContent) self.PLAY() #print(self.ui.file_list.takeItem(0)) def changeTime(self): self.mediaPlayer.positionChanged.disconnect(self.updateTime) print('Time CHANGED') self.mediaPlayer.setPosition(self.ui.sliderTime.value()) localTime = QTime(0, 0, 0) currentTime = localTime.addMSecs(self.mediaPlayer.position()) self.ui.timePlayed.setText(currentTime.toString("HH:mm:ss")) self.mediaPlayer.positionChanged.connect(self.updateTime) def delFile(self): print('delFile PRESSED') rowItem = self.ui.file_list.currentRow() if rowItem != -1: self.ui.file_list.takeItem(rowItem) def nextFile(self): print('nextFile PRESSED') filename = QFileDialog.getOpenFileName(self, "Choix Film") item = QListWidgetItem(filename[0]) self.ui.file_list.addItem(item) def PLAY(self): print('PLAY PRESSED') self.mediaPlayer.setVolume(self.ui.dial_volumen.value()) self.mediaPlayer.play() localTime = QTime(0, 0, 0) totalTime = localTime.addMSecs(self.mediaPlayer.duration()) self.ui.sliderTime.setMaximum(self.mediaPlayer.duration()) self.ui.timeTotal.setText(totalTime.toString("HH:mm:ss")) def PAUSE(self): print('PAUSE PRESSED') if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def PREV(self): print('PREV PRESSED') rowItem = self.ui.file_list.currentRow() if rowItem == -1: return else: self.ui.file_list.setCurrentRow((rowItem - 1)) filename = self.ui.file_list.currentItem().text() print('Loading ' + filename) mediaContent = QMediaContent(QUrl.fromLocalFile(filename)) self.mediaPlayer.setMedia(mediaContent) self.PLAY() def NEXT(self): print('NEXT PRESSED') totalItems = self.ui.file_list.count() rowItem = self.ui.file_list.currentRow() if rowItem + 1 > totalItems: return else: self.ui.file_list.setCurrentRow((rowItem + 1)) filename = self.ui.file_list.currentItem().text() print('Loading ' + filename) mediaContent = QMediaContent(QUrl.fromLocalFile(filename)) self.mediaPlayer.setMedia(mediaContent) self.PLAY() def STOP(self): print('STOP PRESSED') self.mediaPlayer.stop() def get_str_time(t): h, res = divmod(t, 3600) m, s = divmod(res, 60) return f'{int(h):02}:{int(m):02}:{int(s):02}'