class LolitaPlayer(QMediaPlayer): """控制萝莉声音""" def __init__(self, playList = [], ddir = "data", parent = None): """ @param dfile: 萝莉的音乐配置文件 """ QMediaPlayer.__init__(self, parent) # super(LolitaMusic, self).__init__(parent) try: # 播放列表 self.playList = QMediaPlaylist(parent) # 设置只播放一次 self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemOnce) # 读取配置文件中的音乐路径 self._playList = playList # 添加到列表里 self.playList.addMedia([QMediaContent(QUrl(item[1].format(DATA_DIR = ddir))) for item in self._playList]) self.playList.setCurrentIndex(0) # 设置播放列表 self.setPlaylist(self.playList) # 设置音量 self.setVolume(100) except Exception as e: traceback.print_exc(e) def __del__(self): if hasattr(self, "playList"): del self.playList def currentIndex(self): if hasattr(self, "playList"): return self.playList.currentIndex() return 0 def mediaCount(self): if hasattr(self, "_playList"): return len(self._playList) return 0 def setCurrentIndex(self, i): if hasattr(self, "playList"): self.playList.setCurrentIndex(i) def getText(self, i): """获取当前歌曲对应的文字""" if hasattr(self, "_playList"): try: return self._playList[i][0] except Exception as e: traceback.print_exc(e) return "" def play(self, i): """播放指定的歌曲""" if hasattr(self, "playList"): self.playList.setCurrentIndex(i) # 切换到第几首 QMediaPlayer.play(self) # 播放一次 def stop(self): QMediaPlayer.stop(self)
class SoundPack: def __init__(self, name, bg, shoot, hit, score_up, swap, loose, win): """ Creates Soundpack name - soundpack name other params - non-absolute way to files """ self.name = name self.back = QMediaPlaylist() for sound in bg: url = QUrl.fromLocalFile(os.path.join(os.getcwd(), sound)) self.back.addMedia(QMediaContent(url)) self.back.setPlaybackMode(QMediaPlaylist.Loop) self.bg = QMediaPlayer() self.bg.setPlaylist(self.back) self.bg.setVolume(30) self.shoot = QSound(shoot) self.hit = QSound(hit) self.score_up = QSound(score_up) self.swap = QSound(swap) self.loose = QSound(loose) self.win = QSound(win)
class VideoPlayer(QMainWindow): def __init__(self): super(VideoPlayer, self).__init__() self._screen_size = QApplication.primaryScreen().size() sw, sh = self._screen_size.width(), self._screen_size.height() self.resize(sw, sh) self.setStyleSheet('background: black') # # PLAYER self._playList = QMediaPlaylist() self._playWidget = QVideoWidget(self) self._playWidget.resize(sw, sh) self._player = QMediaPlayer(self) self._player.setPlaylist(self._playList) self._player.setVideoOutput(self._playWidget) self._playList.addMedia(QMediaContent( QUrl.fromLocalFile('/Users/huangkai/Documents/PycharmProjects/AllTest/Qt插入背景/AddVideos/Videos/yellow.mov'))) self._playList.setPlaybackMode(QMediaPlaylist.Loop) self._player.play() def keyPressEvent(self, a0: QKeyEvent) -> None: key = a0.key() if key == Qt.Key_Escape: self.resize(100, 100) self._playWidget.resize(100, 100) self._player.stop() elif key in (Qt.Key_Return, Qt.Key_Enter): self.resize(self._screen_size.width(), self._screen_size.height())
def setup_playlist(self): music = QMediaPlaylist() if not self.check_music_file(self._music_track): return None music.addMedia(QMediaContent(QUrl.fromLocalFile(self._music_track))) music.setPlaybackMode(QMediaPlaylist.Loop) return music
class PlayVideo(DisplayEvent): def __init__(self, frame, settings): super().__init__(frame, settings) self.url = QUrl(settings.get("url")) self.start_time = settings.get("start", 0) * 1000 self.duration = settings.get("duration") self.loop = settings.get("loop", True) self.volume = settings.get("volume", 100) self.playback_rate = settings.get("playbackRate", 1.0) def do_tick(self): if self.player: self.logging.info("position: %s/%s status: %s error: %s" % ( self.player.position(), self.player.duration(), self.player.mediaStatus(), self.player.errorString(), )) if self.player.errorString(): self.logging.error(self.player.errorString()) self.cancel() def do_initialize(self): super().do_initialize() self.video = QVideoWidget(self.widget) self.add_widget(self.video) self.video.show() self.media = QMediaContent(self.url) self.playlist = QMediaPlaylist(self.video) self.playlist.addMedia(self.media) self.playlist.setPlaybackMode( QMediaPlaylist.Loop if self.loop else QMediaPlaylist.Sequential) self.player = QMediaPlayer(self.widget) self.player.setVideoOutput(self.video) self.player.setVolume(self.volume) self.player.setPlaybackRate(self.playback_rate) def do_run(self): super().do_run() self.player.setPlaylist(self.playlist) self.player.setPosition(self.start_time) self.player.play() if self.player.errorString(): self.logging.error(self.player.errorString()) self.cancel() def do_stop(self): super().do_stop() self.player.stop() def do_reset(self): self.player = None self.video = None
def play_music(): playlist = QMediaPlaylist(self) url = QUrl.fromLocalFile( resource_path("Wham! - Last Christmas.mp3")) playlist.addMedia(QMediaContent(url)) playlist.setPlaybackMode(QMediaPlaylist.Loop) player = QMediaPlayer(self) player.setPlaylist(playlist) player.play()
def __init__(self, path): super().__init__() if path: sound = QMediaContent(QUrl.fromLocalFile(get_path(path))) self.setMedia(sound) else: play_list = QMediaPlaylist() play_list.setPlaybackMode(QMediaPlaylist.Sequential) self.setPlaylist(play_list) self.play_list = play_list
class WelcomeWindow(QMainWindow, Ui_WelcomeWindow): def __init__(self, welcomeVid): super(self.__class__, self).__init__() self.setupUi(self) self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.pList = QMediaPlaylist() media = QUrl("file://" + welcomeVid) self.pList.addMedia(QMediaContent(media)) self.player.setPlaylist(self.pList) self.pList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.player.setVideoOutput(self.welcomeVideo)
class musicPlayer(QObject): def __init__(self): super().__init__() self.playlist = QMediaPlaylist() self.url = QUrl.fromLocalFile('Music/1.mp3') self.playlist.addMedia(QMediaContent(self.url)) self.url = QUrl.fromLocalFile('Music/2.mp3') self.playlist.addMedia(QMediaContent(self.url)) self.url = QUrl.fromLocalFile('Music/3.mp3') self.playlist.addMedia(QMediaContent(self.url)) self.url = QUrl.fromLocalFile('Music/4.mp3') self.playlist.addMedia(QMediaContent(self.url)) self.playlist.setPlaybackMode(QMediaPlaylist.Loop) print("stigao do 1") self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self.player.play() print("stigao do 2") #self.player.setMuted(True)
class WaitWidget(QVideoWidget, Ui_WaitWidget): pressedSignal = pyqtSignal() def __init__(self, waitVid): super(self.__class__, self).__init__() self.setupUi(self) self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.pList = QMediaPlaylist() media = QUrl("file://" + waitVid) self.pList.addMedia(QMediaContent(media)) self.player.setPlaylist(self.pList) self.pList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.player.setVideoOutput(self) self.setFullScreen(True) def mousePressEvent(self, event): self.pressedSignal.emit() def keyPressEvent(self, event): self.pressedSignal.emit()
class SoundPlayer: def __init__(self, parent): self.parent = parent self.player = QMediaPlayer() self.playlist = QMediaPlaylist() def play(self, playlists, startRow=0, option=QMediaPlaylist.Sequential): if self.player.state() == QMediaPlayer.PausedState: self.player.play() else: self.createPlaylist(playlists, startRow, option) self.player.setPlaylist(self.playlist) self.playlist.setCurrentIndex(startRow) self.player.play() def pause(self): self.player.pause() def stop(self): self.player.stop() def createPlaylist(self, playlists, startRow=0, option=QMediaPlaylist.Sequential): self.playlist.clear() for path in playlists: url = QUrl.fromLocalFile(path) self.playlist.addMedia(QMediaContent(url)) self.playlist.setPlaybackMode(option) def upateVolume(self, vol): self.player.setVolume(vol)
def load_loop(self, name): global config play_loop = QMediaPlaylist() play_loop.addMedia(QMediaContent(QUrl.fromLocalFile(config['preview_path'] + name))) play_loop.setPlaybackMode(QMediaPlaylist.Loop) self.mediaPlayer.setPlaylist(play_loop)
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.time_label = QLabel(self) self.volume_slider = QSlider(self) self.progress_slider = QSlider(self) self.sound_btn = QPushButton(self) self.previous_btn = QPushButton(self) self.play_pause_btn = QPushButton(self) self.next_btn = QPushButton(self) self.mode_btn = QPushButton(self) self.list_btn = QPushButton(self) self.list_widget = QListWidget(self) self.h1_layout = QHBoxLayout() self.h2_layout = QHBoxLayout() self.all_v_layout = QVBoxLayout() self.playlist = QMediaPlaylist(self) self.player = QMediaPlayer(self) self.widget_init() self.layout_init() self.signal_init() def widget_init(self): self.time_label.setText('--/--') self.volume_slider.setRange(0, 100) self.volume_slider.setValue(100) self.volume_slider.setOrientation(Qt.Horizontal) self.progress_slider.setEnabled(False) self.progress_slider.setOrientation(Qt.Horizontal) self.sound_btn.setIcon(QIcon('images/sound_on.png')) self.previous_btn.setIcon(QIcon('images/previous.png')) self.play_pause_btn.setIcon(QIcon('images/play.png')) self.next_btn.setIcon(QIcon('images/next.png')) self.mode_btn.setIcon(QIcon('images/list_loop.png')) self.list_btn.setIcon(QIcon('images/show.png')) self.player.setPlaylist(self.playlist) self.media_list = ['/Users/louis/Downloads/music1.mp3', '/Users/louis/Downloads/music2.mp4', '/Users/louis/Downloads/music3.mp3'] for m in self.media_list: self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(m))) self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.list_widget.addItems([m.split('/')[-1] for m in self.media_list]) def layout_init(self): self.h1_layout.addWidget(self.progress_slider) self.h1_layout.addWidget(self.time_label) self.h2_layout.addWidget(self.volume_slider) self.h2_layout.addWidget(self.sound_btn) self.h2_layout.addWidget(self.previous_btn) self.h2_layout.addWidget(self.play_pause_btn) self.h2_layout.addWidget(self.next_btn) self.h2_layout.addWidget(self.mode_btn) self.h2_layout.addWidget(self.list_btn) self.all_v_layout.addLayout(self.h1_layout) self.all_v_layout.addLayout(self.h2_layout) self.all_v_layout.addWidget(self.list_widget) self.all_v_layout.setSizeConstraint(QVBoxLayout.SetFixedSize) self.setLayout(self.all_v_layout) def signal_init(self): self.sound_btn.clicked.connect(lambda: self.btn_func(self.sound_btn)) self.previous_btn.clicked.connect(lambda: self.btn_func(self.previous_btn)) self.play_pause_btn.clicked.connect(lambda: self.btn_func(self.play_pause_btn)) self.next_btn.clicked.connect(lambda: self.btn_func(self.next_btn)) self.mode_btn.clicked.connect(lambda: self.btn_func(self.mode_btn)) self.list_btn.clicked.connect(lambda: self.btn_func(self.list_btn)) self.volume_slider.valueChanged.connect(self.volume_slider_func) self.list_widget.doubleClicked.connect(self.list_play_func) self.player.durationChanged.connect(self.get_duration_func) self.player.positionChanged.connect(self.get_position_func) self.progress_slider.sliderMoved.connect(self.update_position_func) def btn_func(self, btn): if btn == self.sound_btn: if self.player.isMuted(): self.player.setMuted(False) self.sound_btn.setIcon(QIcon('images/sound_on')) else: self.player.setMuted(True) self.sound_btn.setIcon(QIcon('images/sound_off')) elif btn == self.previous_btn: if self.playlist.currentIndex() == 0: self.playlist.setCurrentIndex(self.playlist.mediaCount() - 1) else: self.playlist.previous() elif btn == self.play_pause_btn: if self.player.state() == 1: self.player.pause() self.play_pause_btn.setIcon(QIcon('images/play.png')) else: self.player.play() self.play_pause_btn.setIcon(QIcon('images/pause.png')) elif btn == self.next_btn: if self.playlist.currentIndex() == self.playlist.mediaCount() - 1: self.playlist.setCurrentIndex(0) else: self.playlist.next() elif btn == self.mode_btn: if self.playlist.playbackMode() == 2: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.mode_btn.setIcon(QIcon('images/item_loop.png')) elif self.playlist.playbackMode() == 3: self.playlist.setPlaybackMode(QMediaPlaylist.Random) self.mode_btn.setIcon(QIcon('images/random.png')) elif self.playlist.playbackMode() == 4: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.mode_btn.setIcon(QIcon('images/list_loop.png')) elif btn == self.list_btn: if self.list_widget.isHidden(): self.list_widget.show() self.list_btn.setIcon(QIcon('images/show.png')) else: self.list_widget.hide() self.list_btn.setIcon(QIcon('images/hide.png')) def volume_slider_func(self, value): self.player.setVolume(value) if value == 0: self.sound_btn.setIcon(QIcon('images/sound_off.png')) else: self.sound_btn.setIcon(QIcon('images/sound_on.png')) def list_play_func(self): self.playlist.setCurrentIndex(self.list_widget.currentRow()) self.player.play() self.play_pause_btn.setIcon(QIcon('images/pause.png')) def get_duration_func(self, d): self.progress_slider.setRange(0, d) self.progress_slider.setEnabled(True) self.get_time_func(d) def get_time_func(self, d): seconds = int(d / 1000) minutes = int(seconds / 60) seconds -= minutes * 60 if minutes == 0 and seconds == 0: self.time_label.setText('--/--') self.play_pause_btn.setIcon(QIcon('images/play.png')) else: self.time_label.setText('{}:{}'.format(minutes, seconds)) def get_position_func(self, p): self.progress_slider.setValue(p) def update_position_func(self, v): self.player.setPosition(v) d = self.progress_slider.maximum() - v self.get_time_func(d)
class BasicVideoWidget(QVideoWidget): def __init__(self, *args, **kwargs): super(BasicVideoWidget, self).__init__(*args, **kwargs) self.mediaPlayer = QMediaPlayer(parent=self) self.setMediaObject(self.mediaPlayer) self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.mediaPlayer.setPlaylist(self.playlist) self.mediaPlayer.positionChanged.connect(self._positionChanged) self.mediaPlayer.mutedChanged.connect(self.mutedChanged) self.mediaPlayer.durationChanged.connect(self._durationChanged) self.mediaPlayer.stateChanged.connect(self.stateChanged) self.mediaPlayer.seekableChanged.connect(self.seekableChanged) def loadUrl(self, url): mc = QMediaContent(url) self.playlist.clear() self.playlist.addMedia(mc) def load(self, path): self.loadUrl(QUrl.fromLocalFile(os.path.abspath(path))) @Slot() def play(self): self.mediaPlayer.play() @Slot() def pause(self): self.mediaPlayer.pause() @Slot() def stop(self): self.mediaPlayer.stop() @Slot(bool) def setMuted(self, b): self.mediaPlayer.setMuted(b) mutedChanged = Signal(bool) @Slot() def playPause(self): if self.mediaPlayer.state() != QMediaPlayer.PlayingState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def state(self): return self.mediaPlayer.state() stateChanged = Signal(QMediaPlayer.State) def duration(self): return self.mediaPlayer.duration() durationChanged = Signal(int) @Slot(int) def setPosition(self, p): self.mediaPlayer.setPosition(p) def position(self): return self.mediaPlayer.position() @Slot('qint64') def _positionChanged(self, p): self.positionChanged.emit(p) positionChanged = Signal(int) @Slot('qint64') def _durationChanged(self, p): self.durationChanged.emit(p) seekableChanged = Signal(bool) def isSeekable(self): return self.mediaPlayer.isSeekable()
class clipEditor(QMainWindow): downloaded_more_scripts = pyqtSignal() def __init__(self, videoWrapper): QtWidgets.QWidget.__init__(self) uic.loadUi(f"{current_path}/UI/ClipEditor.ui", self) try: self.setWindowIcon(QIcon('Assets/tiktoklogo.png')) except Exception as e: pass #Variables and stuff for the editor to send to the video generator self.videoWrapper = videoWrapper self.mainCommentIndex = 0 self.populateTreeWidget() self.treeWidget.currentItemChanged.connect(self.setSelection) self.treeWidget.clicked.connect(self.setSelection) self.downloaded_more_scripts.connect(self.receiveMoreClips) self.introClipPath = None self.firstClipPath = None self.intervalClipPath = None self.outroClipPath = None self.keep = [] #All of the stuff to make the clip editor work self.playlist = QMediaPlaylist() vid_path = QUrl.fromLocalFile(f'{current_path}/VideoFiles') self.mediaPlayer = QMediaPlayer() self.playPauseButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) #self.addClipsToPlaylist() self.mediaPlayer.stateChanged.connect(self.playPauseMedia) self.mediaPlayer.setVideoOutput(self.clipPlayer) self.mediaPlayer.setPlaylist(self.playlist) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.videoDurationSlider.sliderMoved.connect(self.setPosition) self.defaultIntro.stateChanged.connect(self.defaultIntroToggle) self.chooseFirstClip.clicked.connect(self.firstClipFileDialog) self.chooseIntro.clicked.connect(self.introFileDialog) self.chooseInterval.clicked.connect(self.intervalFileDialog) self.chooseOutro.clicked.connect(self.outroFileDialog) self.timer = QTimer(self, interval=1) self.timer.start() self.mediaPlayer.positionChanged.connect(self.vidTimeStamp) self.playPauseButton.clicked.connect(self.play) self.skipButton.clicked.connect(self.skipComment) self.downloadMore.clicked.connect(self.downloadMoreScripts) self.keepButton.clicked.connect(self.keepComment) self.exportButton.clicked.connect(self.videoExportConfirmation) self.moveDown.clicked.connect(self.moveClipDown) self.moveUp.clicked.connect(self.moveClipUp) #self.nextButton.clicked.connect(self.nextClip) self.playlist.currentIndexChanged.connect(self.checkForLastClip) if settings.enforceInterval: self.loadDefaultInterval() else: self.chooseInterval.hide() self.defaultInterval.hide() if settings.enforceIntro: self.loadDefaultIntro() else: self.chooseIntro.hide() self.defaultIntro.hide() if settings.enforceOutro: self.loadDefaultOutro() else: self.chooseOutro.hide() self.defaultOutro.hide() if not settings.enforceFirstClip: self.chooseFirstClip.hide() self.firstClipCred.hide() self.firstClipNameLabel.hide() self.updateDisplay() def muteBackgroundVolume(self): self.backgroundVolume.setText("0") def defaultIntroToggle(self): print(self.defaultIntro.isChecked()) def receiveMoreClips(self): self.populateTreeWidget() def downloadMoreScripts(self): self.gameSelect = ClipDownloadMenu(self) self.gameSelect.show() pass def moveClipDown(self): self.videoWrapper.scriptWrapper.moveUp(self.mainCommentIndex) self.updateDisplay() def moveClipUp(self): self.videoWrapper.scriptWrapper.moveDown(self.mainCommentIndex) self.updateDisplay() def updateDisplay(self): #self.scriptWrapper.saveScriptWrapper() self.getCurrentWidget(self.mainCommentIndex).setForeground( 0, QtGui.QBrush(QtGui.QColor("blue"))) twitchclip = self.videoWrapper.scriptWrapper.getCommentInformation( self.mainCommentIndex) mp4file = twitchclip.mp4 video_duration = twitchclip.vid_duration audio = twitchclip.audio self.clipTitle.setText( f'{twitchclip.author_name}-{twitchclip.clip_name}') self.likeCount.setText("Likes: %s" % twitchclip.diggCount) self.shareCount.setText("Shares: %s" % twitchclip.shareCount) self.playCount.setText("Plays: %s" % twitchclip.playCount) self.commentCount.setText("Comments: %s" % twitchclip.commentCount) self.updateClipDuration() self.mediaPlayer.stop() if len(mp4file.split("/")) > 2: self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(f'{current_path}/{mp4file}'))) else: self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( f'{current_path}/TempClips/{mp4file}.mp4'))) self.mediaPlayer.setVolume(audio * 100) self.estTime.setText( str(self.videoWrapper.scriptWrapper.getEstimatedVideoTime())) self.videoLength.setText(f'{round(video_duration, 1)}') self.mediaPlayer.play() self.clipCountLabel.setText( f"Clip {self.mainCommentIndex+1}/{len(self.videoWrapper.scriptWrapper.rawScript)}" ) def setSelection(self): try: self.currentTreeWidget = self.treeWidget.currentItem() if self.currentTreeWidget.parent() is None: self.mainCommentIndex = int( str(self.currentTreeWidget.text(0)).split(" ")[1]) self.updateColors() self.updateDisplay() except Exception: print("error trying to update selection index") def getCurrentWidget(self, x): return self.getTopLevelByName("Vid %s" % str(x)) def incrimentSelection(self): if not self.mainCommentIndex + 1 > self.videoWrapper.scriptWrapper.getCommentAmount( ) - 1: self.mainCommentIndex += 1 def updateColors(self): for x, mainComment in enumerate( self.videoWrapper.scriptWrapper.scriptMap): self.selectedMainComment = self.getTopLevelByName("Vid %s" % str(x)) if mainComment is True: self.selectedMainComment.setForeground( 0, QtGui.QBrush(QtGui.QColor("green"))) else: self.selectedMainComment.setForeground( 0, QtGui.QBrush(QtGui.QColor("red"))) def keepComment(self): self.videoWrapper.scriptWrapper.keep(self.mainCommentIndex) self.incrimentSelection() self.updateColors() self.updateDisplay() def skipComment(self): self.videoWrapper.scriptWrapper.skip(self.mainCommentIndex) self.updateColors() self.nextMainComment() self.updateDisplay() def nextMainComment(self): if not self.mainCommentIndex + 1 > self.videoWrapper.scriptWrapper.getCommentAmount( ) - 1: self.mainCommentIndex += 1 self.selectedMainComment = self.getTopLevelByName( "Main Comment %s" % str(self.mainCommentIndex)) def populateTreeWidget(self): self.treeWidget.clear() for i, clip in enumerate(self.videoWrapper.scriptWrapper.rawScript): treeParentName = "Vid %s" % str(i) self.addTopLevel(treeParentName) self.selectedMainComment = self.getTopLevelByName("Vid %s" % str(0)) self.updateColors() def getTopLevelByName(self, name): for index in range(self.treeWidget.topLevelItemCount()): item = self.treeWidget.topLevelItem(index) if item.text(0) == name: return item return None def addTopLevel(self, name): if self.getTopLevelByName(name) is None: QTreeWidgetItem(self.treeWidget, [name]) def checkForLastClip(self): if self.playlist.currentIndex() == len(self.startCut) - 1: self.playlist.setPlaybackMode(0) def updateClipDuration(self): twitchclip = self.videoWrapper.scriptWrapper.getCommentInformation( self.mainCommentIndex) #self.clipDurationLabel.setText(f'Clip Duration: {duration}') #Getting the timestamp for the video player def vidTimeStamp(self): self.timeStamp.setText(f"00:{self.getPositionInSecs()}") #Controlling the play/pause of the videos, kinda obvious def playPauseMedia(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playPauseButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playPauseButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) #Giving the play button function def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() #This makes the duration slider move with the video def positionChanged(self, position): self.videoDurationSlider.setValue(position) #Sets the range of each slider to the duration of each video def durationChanged(self, duration): self.videoDurationSlider.setRange(0, duration) #This is to control the position of the video in the media player so I can control the video with the duration slider def setPosition(self, position): self.mediaPlayer.setPosition(position) self.mediaPlayer.play() def introFileDialog(self): options = QFileDialog.Options() fileName, _ = QFileDialog.getOpenFileName( self, "Select The Intro Clip", f"{current_path}/Intros", "All Files (*);;MP4 Files (*.mp4)", options=options) if fileName: try: vid = cv2.VideoCapture(fileName) height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT) width = vid.get(cv2.CAP_PROP_FRAME_WIDTH) if width != int(1920) or height != int(1080): self.uploadFail( "Incorrect resolution for file %s.\n Resolution was %sx%s, required 1920x1080" % (fileName, width, height)) else: self.introClipPath = fileName self.chooseIntro.setText("Reselect Intro") except Exception as e: self.uploadFail("Error occured uploading file \n %s" % (e)) def outroFileDialog(self): options = QFileDialog.Options() fileName, _ = QFileDialog.getOpenFileName( self, "Select The Outro Clip", f"{current_path}/Outros", "All Files (*);;MP4 Files (*.mp4)", options=options) if fileName: try: vid = cv2.VideoCapture(fileName) height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT) width = vid.get(cv2.CAP_PROP_FRAME_WIDTH) if int(width) != 1920 or int(height) != 1080: self.uploadFail( "Incorrect resolution for file %s.\n Resolution was %sx%s, required 1920x1080" % (fileName, width, height)) else: self.outroClipPath = fileName self.chooseOutro.setText("Reselect Outro") except Exception as e: self.uploadFail("Error occured uploading file \n %s" % (e)) def intervalFileDialog(self): options = QFileDialog.Options() fileName, _ = QFileDialog.getOpenFileName( self, "Select The Interval Clip", f"{current_path}/Intervals", "All Files (*);;MP4 Files (*.mp4)", options=options) if fileName: try: vid = cv2.VideoCapture(fileName) height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT) width = vid.get(cv2.CAP_PROP_FRAME_WIDTH) if int(width) != 1920 or int(height) != 1080: self.uploadFail( "Incorrect resolution for file %s.\n Resolution was %sx%s, required 1920x1080" % (fileName, width, height)) else: self.intervalClipPath = fileName self.chooseInterval.setText("Reselect Interval") except Exception as e: self.uploadFail("Error occured uploading file \n %s" % (e)) def firstClipFileDialog(self): options = QFileDialog.Options() fileName, _ = QFileDialog.getOpenFileName( self, "Select The First Clip", f"{current_path}/FirstClips", "All Files (*);;MP4 Files (*.mp4)", options=options) if fileName: # name = len(fileName.split("/")) # self.firstClipPath = (fileName.split("/")[name-1]) try: vid = cv2.VideoCapture(fileName) height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT) width = vid.get(cv2.CAP_PROP_FRAME_WIDTH) if int(width) != 1920 or int(height) != 1080: self.uploadFail( "Incorrect resolution for file %s.\n Resolution was %sx%s, required 1920x1080" % (fileName, width, height)) else: self.firstClipPath = fileName name = len(self.firstClipPath.split("/")) new_name = (self.firstClipPath.split("/")[name - 1]).replace( ".mp4", "") self.firstClipCred.setText(new_name) firstClip = scriptwrapper.DownloadedTwitchClipWrapper( "", "", "", "", None, 0, 0, 0, 0) firstClip.author_name = new_name firstClip.mp4 = self.firstClipPath firstClip.upload = True media_info = MediaInfo.parse(self.firstClipPath) duration = media_info.tracks[0].duration / 1000 firstClip.vid_duration = float(duration) self.videoWrapper.scriptWrapper.addClipAtStart(firstClip) self.populateTreeWidget() self.chooseFirstClip.setText("Reselect First Clip") except Exception as e: self.uploadFail("Error occured uploading file \n %s" % (e)) def saveDefaultIntro(self): with open(f'Save Data/defaultintro.save', 'wb') as pickle_file: pickle.dump(self.introClip, pickle_file) def saveDefaultInterval(self): with open(f'Save Data/defaultinterval.save', 'wb') as pickle_file: pickle.dump(self.intervalClipPath, pickle_file) def saveDefaultOutro(self): with open(f'Save Data/defaultoutro.save', 'wb') as pickle_file: pickle.dump(self.outroClipPath, pickle_file) def loadDefaultIntro(self): if os.path.exists("Save Data/defaultintro.save"): with open(f'Save Data/defaultintro.save', 'rb') as pickle_file: self.introClip = pickle.load(pickle_file) self.introClipPath = self.introClip.mp4 self.defaultIntro.setChecked(True) self.chooseIntro.setText("Reselect Intro") def loadDefaultInterval(self): if os.path.exists("Save Data/defaultinterval.save"): with open(f'Save Data/defaultinterval.save', 'rb') as pickle_file: self.intervalClip = pickle.load(pickle_file) self.intervalClipPath = self.intervalClip self.defaultInterval.setChecked(True) self.chooseInterval.setText("Reselect Interval") def loadDefaultOutro(self): if os.path.exists("Save Data/defaultoutro.save"): with open(f'Save Data/defaultoutro.save', 'rb') as pickle_file: self.outroClip = pickle.load(pickle_file) self.outroClipPath = self.outroClip self.defaultOutro.setChecked(True) self.chooseOutro.setText("Reselect Outro") #Collecting all of the information for video generator def exportVideo(self): intervalCheck = True if (self.intervalClipPath is not None and settings.enforceInterval ) or not settings.enforceInterval else False firstClipCheck = True if (self.firstClipPath is not None and settings.enforceFirstClip ) or not settings.enforceFirstClip else False introClipCheck = True if ( self.introClipPath is not None and settings.enforceIntro) or not settings.enforceIntro else False outroClipCheck = True if ( self.outroClipPath is not None and settings.enforceOutro) or not settings.enforceOutro else False if intervalCheck is True and firstClipCheck is True and introClipCheck is True and outroClipCheck is True: self.mediaPlayer.stop() final_clips = self.videoWrapper.scriptWrapper.getFinalClips() with_intro = [] if settings.enforceIntro: self.introClip = scriptwrapper.DownloadedTwitchClipWrapper( "", "", " ", "", None, 0, 0, 0, 0) self.introClip.author_name = None self.introClip.mp4 = self.introClipPath self.introClip.isIntro = True self.introClip.isInterval = False self.introClip.upload = True self.introClip.isUsed = True media_info_intro = MediaInfo.parse(self.introClipPath) duration_intro = media_info_intro.tracks[0].duration / 1000 self.introClip.vid_duration = float(duration_intro) if settings.enforceInterval: self.intervalClip = scriptwrapper.DownloadedTwitchClipWrapper( "", "", " ", "", None, 0, 0, 0, 0) self.intervalClip.author_name = None self.intervalClip.mp4 = self.intervalClipPath self.intervalClip.isInterval = True self.intervalClip.isIntro = False self.intervalClip.upload = True self.intervalClip.isUsed = True media_info_interval = MediaInfo.parse(self.intervalClipPath) duration_interval = media_info_interval.tracks[ 0].duration / 1000 self.intervalClip.vid_duration = float(duration_interval) if settings.enforceOutro: self.outroClip = scriptwrapper.DownloadedTwitchClipWrapper( "", "", " ", "", None, 0, 0, 0, 0) self.outroClip.author_name = None self.outroClip.mp4 = self.outroClipPath self.outroClip.isOutro = True self.outroClip.upload = True self.outroClip.isUsed = True media_info_outro = MediaInfo.parse(self.outroClipPath) duration_outro = media_info_outro.tracks[0].duration / 1000 self.outroClip.vid_duration = float(duration_outro) if self.defaultIntro.isChecked(): self.saveDefaultIntro() if self.defaultInterval.isChecked(): self.saveDefaultInterval() if self.defaultOutro.isChecked(): self.saveDefaultOutro() for i, clip in enumerate(final_clips): with_intro.append(clip) if i == 0: if settings.enforceInterval: with_intro.append(self.intervalClip) if settings.enforceIntro: with_intro.append(self.introClip) if settings.enforceOutro: with_intro.append(self.outroClip) self.videoWrapper.final_clips = with_intro self.clipupload = ClipUploadMenu(self.videoWrapper, self.videoName.text()) self.clipupload.show() else: print("Choose intro clip and first clip") #Converting the video duration/position to seconds so it makes sense def getPositionInSecs(self): try: index = self.playlist.currentIndex() vid_position = self.mediaPlayer.position() vid_duration = self.mediaPlayer.duration() vid_percentage = (vid_position / vid_duration) twitchclip = self.videoWrapper.scriptWrapper.getCommentInformation( self.mainCommentIndex) return int(twitchclip.vid_duration * vid_percentage) except: pass def videoExportConfirmation(self): msg = 'Is the video long enough?\nIs everything properly cut?' buttonReply = QMessageBox.information( self, 'Video Export Confirmation', msg, QMessageBox.Yes | QMessageBox.Cancel, QMessageBox.Cancel) if buttonReply == QMessageBox.Yes: intervalCheck = True if ( self.intervalClipPath is not None and settings.enforceInterval ) or not settings.enforceInterval else False firstClipCheck = True if ( self.firstClipPath is not None and settings.enforceFirstClip ) or not settings.enforceFirstClip else False introClipCheck = True if (self.introClipPath is not None and settings.enforceIntro ) or not settings.enforceIntro else False outroClipCheck = True if (self.outroClipPath is not None and settings.enforceOutro ) or not settings.enforceOutro else False msg = "Could not publish due to the following reasons: \n" if not intervalCheck: msg += "No interval selected, but interval expected (see config.ini)\n" if not firstClipCheck: msg += "No first clip selected, but first clip expected (see config.ini)\n" if not introClipCheck: msg += "No intro clip selected, but intro expected (see config.ini)\n" if not outroClipCheck: msg += "No outro clip selected, but outro expected (see config.ini)\n" amountClips = len(self.videoWrapper.scriptWrapper.getKeptClips()) if amountClips < 2: msg += "Not enough clips! Need at least two clips to be kept." if intervalCheck is False or firstClipCheck is False or introClipCheck is False or outroClipCheck is False or amountClips < 2: self.publishFail(msg) return self.mediaPlayer.stop() self.close() self.exportVideo() print('Yes clicked.') if buttonReply == QMessageBox.Cancel: print('Cancel') def uploadFail(self, msg): buttonReply = QMessageBox.information(self, 'Upload fail', msg, QMessageBox.Ok) def publishFail(self, msg): buttonReply = QMessageBox.information(self, 'Publish fail', msg, QMessageBox.Ok)
class Start(QMainWindow): def __init__(self): super(Start, self).__init__() self.titles = "Media Player" self.left = 500 self.top = 300 self.width = 400 self.height = 200 self.window_main() self.adding_menus() def openMultipleFile(self): dialogs = QFileDialog(self) self.fnames, _ = dialogs.getOpenFileNames( self, 'Open Media Files', QDir.homePath(), "Videos (*.mp4 *.mkv *.3pg)") if self.fnames != '': self.playlist = QMediaPlaylist(self) self.fnamelist = [] for playlst in self.fnames: self.fnamelist.append( QMediaContent(QUrl.fromLocalFile(playlst))) self.playlist.addMedia(self.fnamelist) self.playlist.setCurrentIndex(1) self.videoWidget = QVideoWidget(self) self.mediaPlayer.setVideoOutput(self.videoWidget) # self.videoWidget.setAspectRatioMode(60, 60,Qt.KeepAspectRatioByExpanding) self.mediaPlayer.setPlaylist(self.playlist) self.playlist.currentIndexChanged.connect(self.mediaNameChange) self.mediaPlayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) self.play.setEnabled(True) self.stop.setEnabled(True) self.loop.setEnabled(True) if (len(self.fnamelist) > 1): self.forw.setEnabled(True) self.shuffl.setEnabled(True) self.l1.setText("00:00") mediaName = self.fnames[0].rsplit('/', 1)[-1] self.fulltitle = mediaName + " - " + self.titles self.setWindowTitle(self.fulltitle) self.mediaPlayer.durationChanged.connect(self.sliderDuration) def openFile(self): self.fname, _ = QFileDialog.getOpenFileName( self, 'Open Media Files', QDir.homePath(), "Videos (*.mp4 *.mkv *.3pg)") if self.fname != '': mediaName = self.fname.rsplit('/', 1)[-1] self.fulltitle = mediaName + " - " + self.titles self.setWindowTitle(self.fulltitle) self.playlist = QMediaPlaylist(self) self.playlist.addMedia( QMediaContent(QUrl.fromLocalFile(self.fname))) self.playlist.setCurrentIndex(1) self.mediaPlayer.setPlaylist(self.playlist) self.playlist.currentIndexChanged.connect(self.mediaNameChange) self.mediaPlayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) self.play.setEnabled(True) self.stop.setEnabled(True) self.loop.setEnabled(True) self.l1.setText("00:00") self.mediaPlayer.durationChanged.connect(self.sliderDuration) def window_main(self): self.setWindowTitle(self.titles) qw = QWidget() self.setGeometry(self.left, self.top, qw.maximumWidth(), qw.maximumHeight()) self.setMinimumSize(540, 0) self.setWindowIcon(QIcon("mediaplayer.png")) self.video() self.show() def sliderChanged(self, position): pos = position * 1000 self.mediaPlayer.setPosition(pos) self.slider.setValue(position) def adding_menus(self): menu = Allmenu(self) def volumeChange(self, vol): self.mediaPlayer.setVolume(vol) def sliderDuration(self, duratn): milisec = self.mediaPlayer.duration() sec = int(milisec / 1000) hour = int(sec / 3600) min = int((sec / 60) - (hour * 60)) secs = int(sec - (min * 60) - (hour * 60 * 60)) self.l2.setText(str(hour) + ":" + str(min) + ":" + str(secs)) self.slider.setMaximum(sec) def sliderDuration2(self, duratn): second = int(duratn / 1000) self.slider.setValue(second) hour = int(second / 3600) min = int((second / 60) - (hour * 60)) secs = int(second - (min * 60) - (hour * 60 * 60)) if (min < 10): min = "0" + str(min) else: min = str(min) if (secs < 10): secs = "0" + str(secs) else: secs = str(secs) if (hour == 0): self.l1.setText(min + ":" + secs) else: self.l1.setText(str(hour) + ":" + min + ":" + secs) def mediaNameChange(self, index): mediaName = self.fnames[index].rsplit('/', 1)[-1] self.fulltitle = mediaName + " - " + self.titles self.setWindowTitle(self.fulltitle) if (self.playlist.playbackMode() == 4): self.forw.setEnabled(True) self.back.setEnabled(True) else: if ((index + 1) == self.playlist.mediaCount()): self.forw.setEnabled(False) self.back.setEnabled(True) else: self.back.setEnabled(True) def video(self): self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.positionChanged.connect(self.sliderDuration2) self.mediaPlayer.setVolume(10) videoWidget = QVideoWidget() layout = QVBoxLayout() wid = QWidget(self) self.play = QPushButton() self.play.setEnabled(False) self.play.setFixedWidth(40) self.play.setFixedHeight(30) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.play.setIconSize(QSize(20, 20)) self.play.clicked.connect(self.playAction) self.play.setShortcut(QKeySequence("Space")) self.back = QPushButton() self.back.setEnabled(False) self.back.setFixedWidth(40) self.back.setFixedHeight(25) self.back.setStyleSheet("margin-left: 10px") self.back.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.back.setIconSize(QSize(14, 14)) self.back.clicked.connect(self.prevAction) self.back.setShortcut(QKeySequence("Ctrl+b")) self.stop = QPushButton() self.stop.setEnabled(False) self.stop.setFixedWidth(40) self.stop.setFixedHeight(25) self.stop.setStyleSheet("margin-left: 0px") self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stop.setIconSize(QSize(14, 14)) self.stop.clicked.connect(self.stopAction) self.stop.setShortcut(QKeySequence("s")) self.forw = QPushButton() self.forw.setEnabled(False) self.forw.setFixedWidth(40) self.forw.setFixedHeight(25) self.forw.setStyleSheet("margin-left: 0px") self.forw.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.forw.setIconSize(QSize(14, 14)) self.forw.clicked.connect(self.forwAction) self.forw.setShortcut(QKeySequence("Ctrl+f")) self.loop = QPushButton() self.loop.setEnabled(False) self.loop.setFixedWidth(40) self.loop.setFixedHeight(25) self.loop.setStyleSheet("margin-left: 10px") self.loop.setIcon(QIcon(QPixmap("loop.svg"))) self.loop.setIconSize(QSize(14, 14)) self.loop.clicked.connect(self.loopAction) self.loop.setShortcut(QKeySequence("Ctrl+l")) self.shuffl = QPushButton() self.shuffl.setEnabled(False) self.shuffl.setFixedHeight(25) self.shuffl.setStyleSheet("margin-left: 0px") self.shuffl.setFixedWidth(40) self.shuffl.setFixedHeight(25) self.shuffl.setStyleSheet("margin-left: 0px") self.shuffl.setIcon(QIcon(QPixmap("shuffl.svg"))) self.shuffl.setIconSize(QSize(14, 14)) self.shuffl.clicked.connect(self.shufflAction) self.shuffl.setShortcut(QKeySequence("Ctrl+shift+s")) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.volume = QDial() self.volume.setFixedWidth(40) self.volume.setFixedHeight(40) self.volume.setMaximum(100) self.volume.setMinimum(0) self.volume.setToolTip("Volume") self.volume.valueChanged.connect(self.volumeChange) hlayout = QHBoxLayout() hlayout.addWidget(self.play) hlayout.addWidget(self.back) hlayout.addWidget(self.stop) hlayout.addWidget(self.forw) hlayout.addWidget(self.loop) hlayout.addWidget(self.shuffl) hlayout.addItem(spacer) hlayout.addWidget(self.volume) hslayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(0) self.l1 = QLabel() self.l1.setText("--:--:--") self.l2 = QLabel() self.l2.setText("--:--:--") self.slider.sliderMoved.connect(self.sliderChanged) hslayout.addWidget(self.l1) hslayout.addWidget(self.slider) hslayout.addWidget(self.l2) layout.addWidget(videoWidget) layout.addLayout(hslayout) layout.addLayout(hlayout) wid.setLayout(layout) self.setCentralWidget(wid) self.mediaPlayer.setVideoOutput(videoWidget) def playAction(self): if (self.mediaPlayer.state() == 1): self.mediaPlayer.pause() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) elif (self.mediaPlayer.state() == 2): self.mediaPlayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) else: self.back.setEnabled(False) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) def stopAction(self): self.mediaPlayer.stop() self.play.setEnabled(False) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.setWindowTitle(self.titles) self.l1.setText("--:--:--") self.l2.setText("--:--:--") def forwAction(self): if (self.playlist.playbackMode() == 4): self.forw.setEnabled(True) self.back.setEnabled(True) indexes = random.randint(0, (self.playlist.mediaCount() - 1)) self.playlist.setCurrentIndex(indexes) elif (self.playlist.playbackMode() == 1): self.playlist.next() else: print(self.playlist.currentIndex()) if ((self.playlist.currentIndex() + 2) == self.playlist.mediaCount()): self.forw.setEnabled(False) self.playlist.next() self.back.setEnabled(True) else: self.playlist.next() self.back.setEnabled(True) def prevAction(self): if (self.playlist.playbackMode() == 4): self.forw.setEnabled(True) self.back.setEnabled(True) indexes = random.randint(0, (self.playlist.mediaCount() - 1)) self.playlist.setCurrentIndex(indexes) elif (self.playlist.playbackMode() == 1): self.playlist.previous() else: if (self.playlist.currentIndex() == 1): self.forw.setEnabled(True) self.playlist.previous() self.back.setEnabled(False) else: self.playlist.previous() self.forw.setEnabled(True) def loopAction(self): if (self.playlist.playbackMode() != 1): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.loop.setIcon(QIcon(QPixmap("greenloop.svg"))) self.shuffl.setIcon(QIcon(QPixmap("shuffl.svg"))) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.loop.setIcon(QIcon(QPixmap("loop.svg"))) def shufflAction(self): if (self.playlist.playbackMode() != 4): self.playlist.setPlaybackMode(QMediaPlaylist.Random) self.shuffl.setIcon(QIcon(QPixmap("greenshuffl.svg"))) self.loop.setIcon(QIcon(QPixmap("loop.svg"))) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.shuffl.setIcon(QIcon(QPixmap("shuffl.svg"))) def close(self): sys.exit(1)
class MyWidget(QMainWindow): def __init__(self): super().__init__() uic.loadUi('ui/alarm_clock_form.ui', self) self.initUI() self.alarm_clock_list = [] self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.player.setPlaylist(self.playlist) def initUI(self): self.digital_clock = DigitalClock(self.clockWidget) self.digital_clock.time_tick.connect(self.time_tick) clock_widget_layout = QHBoxLayout() clock_widget_layout.addWidget(self.digital_clock) self.clockWidget.setLayout(clock_widget_layout) self.addAlarmClockButton.clicked.connect(self.add_alarm_clock) def closeEvent(self, event): reply = QMessageBox.question(self, 'Выход', "Вы уверены что хотите выйти? Будильники перестанут работать", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() def add_alarm_clock(self): dialog = NewAlarmClockDialog() dialog_result = dialog.exec_() if (dialog_result == QDialog.Accepted): widget_item = QListWidgetItem(self.listWidget); alarm_clock_item = AlarmClockItem(dialog.nameLineEdit.text(), dialog.timeEdit.time(), dialog.filePathLineEdit.text()) alarm_clock_item.alarm.connect(self.alarm) self.alarm_clock_list.append(alarm_clock_item) alarm_clock_item_widget = AlarmClockItemWidget(alarm_clock_item, widget_item, self) alarm_clock_item_widget.alarm_clock_remove.connect(self.alarm_clock_remove) widget_item.setSizeHint(alarm_clock_item_widget.sizeHint()); self.listWidget.setItemWidget(widget_item, alarm_clock_item_widget); dialog.deleteLater() def alarm_clock_remove(self): self.listWidget.takeItem(self.listWidget.row(self.sender().list_widget_item)) self.alarm_clock_list.remove(self.sender().alarm_clock) def time_tick(self): for alarm_clock in self.alarm_clock_list: if alarm_clock.is_active: alarm_clock.tick() def alarm(self): alarm_clock = self.sender() self.play_sound(alarm_clock.alarm_sound) QMessageBox.information(self, 'Будильник', 'Будильник "' + alarm_clock.title + '"', QMessageBox.Ok) alarm_clock.is_alarm = False self.stop_sound() def play_sound(self, sound): if len(sound): self.player.stop() self.playlist.clear() media_content = QMediaContent(QUrl.fromLocalFile(sound)) self.playlist.addMedia(media_content) self.player.play() def stop_sound(self): self.player.stop()
class VideoPlayer(QWidget): def __init__(self, parent=None): # Super (whatever that means) super(VideoPlayer, self).__init__() # Initialize self.setGeometry(400, 100, 1280, 960) self.setWindowTitle('ProjecTosh by Trent Baker (c) 2019') # Set window background color self.setAutoFillBackground(True) p = self.palette() p.setColor(self.backgroundRole(), QColor(53, 64, 38)) self.setPalette(p) # UI and widgets and such # Video widget self.video = QVideoWidget() #self.video.resize(300, 300) #self.video.move(0, 0) # Media Playlist self.playlist = QMediaPlaylist() self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile("video/video.avi"))) # https://www.nps.gov/grca/learn/photosmultimedia/b-roll_hd07.htm (default is public domain b-roll video) self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.playlist.setCurrentIndex(0) # Video player widget self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self.player.setVideoOutput(self.video) #self.player.setMedia() self.player.play() # Label widgets fnt = QtGui.QFont('Impact', 20) h = announcements.announcements[1][0] b = announcements.announcements[1][1] # Announcements body self.lbAnnounce = QLabel() self.lbAnnounce.setText(h+'\n\n'+b) self.lbAnnounce.setFont(fnt) self.lbAnnounce.setAlignment(Qt.AlignTop) self.lbAnnounce.setWordWrap(True) self.lbAnnounce.setMaximumSize(600, 400) self.lbAnnounce.setStyleSheet("color: rgb(250, 241, 205);") # Current day self.lbDay = QLabel() self.lbDay.setText("it's day 1 lol") self.lbDay.setAlignment(Qt.AlignCenter) # Grad events self.lbGrad = QLabel() self.lbGrad.setText('upcoming grad event:\nsled') self.lbGrad.setAlignment(Qt.AlignCenter) # Timer for cycling announcement i = 1 j = 1 # Called when timer hits limit def handler(): nonlocal h, b, i, j # Here i is the 'x' index of the 2D announcements.announcements array, and j is the 'y' j += 1 # Print attempt begin print("Trying announcement at index "+str(i)) # Cycle fake for loop if j >= len(announcements.announcements[i]): j = 1 i += 1 if i >= len(announcements.announcements): i = 1 # Try until get announcement error = True while error: try: h = announcements.announcements[i][0] b = announcements.announcements[i][j] # At present this is only listing the first non-title item in the annoucement lists ann = h + '\n\n' + b print("Successfully updated announcement from index "+str(i)) error = False except: print("Error when converting announcement at index "+str(i)+", skipping") i += 1 # Update announcement text self.lbAnnounce.setText(ann) self.timer = QtCore.QTimer() self.timer.timeout.connect(handler) self.timer.start(2000) # Do the layout move to do the layout move self.grid = QGridLayout() w = 4 h = 3 wl = 2 wr = w-wl ht = 1 hb = h-ht self.grid.addWidget(self.lbDay, 0, 0, ht, wl) self.grid.addWidget(self.lbGrad, ht, 0, hb, wl) self.grid.addWidget(self.video, 0, wl, ht, wr) self.grid.addWidget(self.lbAnnounce, ht, wl, hb, wr) self.setLayout(self.grid)
class MainWindowAction(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindowAction, self).__init__(parent) self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.local_music_path = [] self.setupUi(self) self.init() self.show() def init(self): # self.setWindowFlags(Qt.FramelessWindowHint) self.loadParams() self.playlist.setPlaybackMode(self.playlist.Loop) self.player.setPlaylist(self.playlist) self.player.play() exit_normal_icon_path = QUrl.fromLocalFile(EXIT_ICON_PATH) self.exit_normal_icon = QIcon(EXIT_ICON_PATH) self.exitButton.setStyleSheet(EXIT_BUTTON_STYLE) self.exitButton.clicked.connect(self.close) self.minButton.clicked.connect(self.showMinimized) # self.playButton.clicked.connect(self.playControl) self.nextButton.clicked.connect(self.playlist.next) self.prevButton.clicked.connect(self.playlist.previous) self.playButton.clicked.connect(self.controlPlay) self.player.currentMediaChanged.connect(self.initProgressBar) self.player.stateChanged.connect(self.changePlayState) self.player.positionChanged.connect(self.changeBar) self.playProgressBar.sliderReleased.connect(self.changePlayPosition) def loadParams(self): with open(CONFIG_PATH, 'r') as file: params = json.load(file) self.local_music_dirs = params['initParams']['LocalMusicDirs'] last_playlist = params['lastPlayParams']['Playlist'] self.initPlayList(last_playlist) def initPlayList(self, playlist_name): playlist_path = './PlayList/' + playlist_name + '.json' with open(playlist_path, 'r', encoding='UTF-8') as file: music_list = json.load(file) music_path_list = music_list['Songs'] for music_path in music_path_list: path = QUrl.fromLocalFile(music_path) music = QMediaContent(path) self.playlist.addMedia(music) def controlPlay(self): if self.player.state() == self.player.PlayingState: self.player.pause() # self.playButton.setText("Play") elif self.player.state() == self.player.PausedState: self.player.play() elif self.player.state() == self.player.StoppedState: if self.player.mediaStatus() in [ self.player.LoadingMedia, self.player.LoadedMedia, self.player.BufferedMedia, self.player.BufferingMedia ]: self.player.play() def changePlayState(self): if self.player.state() == self.player.PlayingState: self.playButton.setText("Pause") else: self.playButton.setText("Play") def initProgressBar(self): print(self.playlist.currentMedia().resources()[0].url().fileName()) self.playProgressBar.setValue(0) def changeBar(self): if self.player.state() == self.player.PlayingState: duration = self.player.duration() if duration > 0: value = self.player.position() * 100 // duration self.playProgressBar.setValue(value) def changePlayPosition(self): self.player.pause() duration = self.player.duration() value = self.playProgressBar.value() * duration // 100 self.player.setPosition(value) self.player.play()
class DPlayerCore(QWidget): def __init__(self): """Initialize player and load playlist if any.""" super().__init__() self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.shuffling = False self.repeatingPlaylist = False self.repeatingSong = False self.musicOrder = [] self.loadPlaylist(QUrl( 'file://{}/lastListened.m3u'.format(os.getcwd()))) self.lyricsApi = 'http://api.musixmatch.com/ws/1.1/' self.lyricsApiKey = '4b364f0652e471aa50813a22cdf830ea' self.lastFMapi = 'http://ws.audioscrobbler.com/2.0/' self.lastFMapikey = '052c43a00a4fc294bb3c9e0c38bdf710' self.lastFMsecret = '14c66392fa9c6c142a41ccc2b0674e19' self.username = None self.password = None self.network = None self.error = 'Something went wrong! Try again later.' def play(self): """Start the player.""" self.player.play() def pause(self): """Pause the player.""" self.player.pause() def stop(self): """Stop the player.""" self.player.stop() def previous(self): """Play previous song.""" self.playlist.previous() def next(self): """Play next song.""" self.playlist.next() def mute(self): """Mute the player.""" self.player.setMuted(True) def unmute(self): """Unmute the player.""" self.player.setMuted(False) def setVolume(self, value): """Set player's volume to value.""" self.player.setVolume(value) def add(self, fileNames): """Add fileNames to the playlist.""" for name in fileNames: url = QUrl.fromLocalFile(QFileInfo(name).absoluteFilePath()) self.playlist.addMedia(QMediaContent(url)) self.musicOrder.append([name]) self.added(len(fileNames)) def added(self, added): """Saves music info in musicOrder.""" for name, index in zip( self.musicOrder[self.playlist.mediaCount() - added:], range(self.playlist.mediaCount() - added, len(self.musicOrder))): name = name[0] artist = self.getArtist(name)[0] title = self.getTitle(name)[0] album = self.getAlbum(name)[0] seconds = self.getDuration(name) duration = QTime(0, seconds // 60, seconds % 60) duration = duration.toString('mm:ss') self.musicOrder[index].extend( [artist, title, album, duration]) def remove(self, songIndexes): """Remove songIndexes from the playlist.""" for index in songIndexes: self.songChanged = True del self.musicOrder[index] self.playlist.removeMedia(index) self.songChanged = False def savePlaylist(self, path): """Save playlist to path.""" if path.toString()[len(path.toString()) - 4:] != '.m3u': path = QUrl('{}.m3u'.format(path.toString())) self.playlist.save(path, 'm3u') def loadPlaylist(self, path): """Load playlist form path.""" count = self.playlist.mediaCount() self.playlist.load(path) for index in range(count, self.playlist.mediaCount()): self.musicOrder.append( [self.playlist.media(index).canonicalUrl().path()]) self.added(self.playlist.mediaCount() - count) def clearPlaylist(self): """Delete all songs in the playlist.""" self.playlist.clear() self.musicOrder = [] def shuffle(self, value): """Shuffle playlist if value = True.""" self.shuffling = value if self.repeatingSong: return if self.shuffling: self.playlist.setPlaybackMode(QMediaPlaylist.Random) elif self.repeatingPlaylist: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def repeatPlaylist(self, value): """Repeat playlist after the last song is finished if value = True.""" self.repeatingPlaylist = value if self.repeatingSong or self.shuffling: return if self.repeatingPlaylist: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def repeatSong(self, value): """Repeat current song if value = True.""" self.repeatingSong = value if self.repeatingSong: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) elif self.shuffling: self.playlist.setPlaybackMode(QMediaPlaylist.Random) elif self.repeatingPlaylist: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def sort(self, column, order): """Sort playlist by column in order.""" ordered = sorted(self.musicOrder, key=itemgetter(column + 1), reverse=order) self.clearPlaylist() for song in ordered: url = QUrl.fromLocalFile(QFileInfo(song[0]).absoluteFilePath()) self.playlist.addMedia(QMediaContent(url)) self.musicOrder = ordered def findLyrics(self, index): """Returns lyrics for song at index.""" if self.musicOrder[index][2] == 'Unknown': return 'Unknown song.' searchSong = '{}track.search?q_track={}'.format( self.lyricsApi, self.musicOrder[index][2].replace(' ', '%20')) if self.musicOrder[index][1] != 'Unknown': searchSong = '{}&q_artist={}'.format( searchSong, self.musicOrder[index][1].replace(' ', '%20')) searchSong = '{}&f_has_lyrics=1&apikey={}'.format( searchSong, self.lyricsApiKey) try: requestSong = requests.get(searchSong) except requests.ConnectionError: return self.error songJson = requestSong.json() if requestSong.status_code != 200 or \ songJson['message']['header']['available'] == 0: return self.error songId = songJson[ 'message']['body']['track_list'][0]["track"]["track_id"] searchLyrics = '{}track.lyrics.get?track_id={}&apikey={}'.format( self.lyricsApi, songId, self.lyricsApiKey) try: requestLyrics = requests.get(searchLyrics) except requests.ConnectionError: return self.error if requestLyrics.status_code != 200 or \ songJson['message']['header']['available'] == 0: return self.error return requestLyrics.json()[ 'message']['body']['lyrics']['lyrics_body'][:-58] # spam and bacon def findInfo(self, index): """Returns info about artist and album for index if any.""" info = [] if self.musicOrder[index][1] != 'Unknown': artist = self.artistInfo(self.musicOrder[index][1]) if artist != self.error: info += artist if self.musicOrder[index][1] != 'Unknown' and \ self.musicOrder[index][3] != 'Unknown': album = self.albumInfo(self.musicOrder[index][1], self.musicOrder[index][3]) if album != self.error: info += album if info: return info else: return ['Unknown artist and song!'] def artistInfo(self, artist): """Returns info about artist if any.""" try: response = requests.get( ('{}/?method=artist.getinfo&artist={}&api_key={}&' 'format=json&autocorrect=1').format( self.lastFMapi, artist, self.lastFMapikey)) except Exception: return self.error if response.status_code != 200: return self.error artist = 'Artist: {}'.format(response.json()['artist']['name']) bio = 'Bio: {}'.format( response.json()['artist']['bio']['summary'].replace('.', '.\n')) spam = bio.find('<a') bio = bio[:spam] return [artist, bio] def albumInfo(self, artist, album): """Returns info about album if any.""" try: response = requests.get( ('{}/?method=album.getinfo&artist={}&album={}&api_key={}&' 'format=json&autocorrect=1').format( self.lastFMapi, artist, album, self.lastFMapikey)) except Exception: return self.error if response.status_code != 200 or \ 'album' not in response.json().keys(): return self.error album = 'Album: {}'.format(response.json()['album']['name']) tracks = ['Tracks: '] t = response.json()['album']['tracks']['track'] for track, index in zip(t, range(len(t))): tracks.append('{}. {}'.format(index + 1, track['name'])) info = [album, '\n'.join(tracks)] if 'wiki' in response.json()['album'].keys(): wiki = response.json()['album']['wiki'] if 'published' in wiki.keys(): info.append('Published: {}'.format(wiki['published'])) if 'summary' in wiki.keys(): summary = wiki['summary'].replace('.', '.\n') spam = summary.find('<a') info.append('Summary: {}'.format(summary[:spam])) if 'Musical style' in wiki.keys(): info.append('Musical style: {}'.format(wiki['Musical style'])) return info def login(self, username, password): """Creates lastFM network.""" self.username = username self.password = pylast.md5(password) try: self.network = pylast.LastFMNetwork(api_key=self.lastFMapikey, api_secret=self.lastFMsecret, username=self.username, password_hash=self.password) except Exception: self.username = None self.password = None self.network = None return False return True def logout(self): """Destoys lastFM network and current user info.""" self.username = None self.password = None self.network = None def loveTrack(self, index): """Love track at index in lastFM.""" if self.network is None: return False track = self.network.get_track(self.musicOrder[index][1], self.musicOrder[index][2]) try: track.love() except Exception: return False return True def unloveTrack(self, index): """Unlove track at index in lastFM.""" if self.network is None: return False track = self.network.get_track(self.musicOrder[index][1], self.musicOrder[index][2]) try: track.unlove() except Exception: return False return True def isMuted(self): """Returns True if player is muted.""" return self.player.isMuted() def getArtist(self, song): """Returns the artist of song.""" if song[-4:] == '.mp3': obj = EasyID3(song) if 'artist' in obj.keys(): return obj['artist'] elif 'TAG' in mediainfo(song).keys(): obj = mediainfo(song)['TAG'] if 'artist' in obj.keys(): return [obj['artist']] elif 'ARTIST' in obj.keys(): return [obj['ARTIST']] else: return ['Unknown'] else: return ['Unknown'] def getTitle(self, song): """Returns the title of song.""" if song[-4:] == '.mp3': obj = EasyID3(song) if 'title' in obj.keys(): return obj['title'] elif 'TAG' in mediainfo(song).keys(): obj = mediainfo(song)['TAG'] if 'title' in obj.keys(): return [obj['title']] elif 'TITLE' in obj.keys(): return [obj['TITLE']] else: return ['Unknown'] else: return ['Unknown'] def getAlbum(self, song): """Returns the album of song.""" if song[-4:] == '.mp3': obj = EasyID3(song) if 'album' in obj.keys(): return obj['album'] elif 'TAG' in mediainfo(song).keys(): obj = mediainfo(song)['TAG'] if 'album' in obj.keys(): return [obj['album']] elif 'ALBUM' in obj.keys(): return [obj['ALBUM']] else: return ['Unknown'] else: return ['Unknown'] def getDuration(self, song): """Returns the duration of song.""" if song[-4:] == '.mp3': return MP3(song).info.length return int(float(mediainfo(song)['duration']))
class PMusic(QWidget): '''central widget''' DEFAULT_IMG = '/usr/share/pmusic/pMusic.png' def __init__(self, parent): '''initialize instance''' super().__init__(parent) self.player = QMediaPlayer() self.player.mediaStatusChanged.connect(self.onmedia_status_changed) self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.player.setVolume(100) self.resize(parent.width(), parent.height()) self.setContentsMargins(0, 0, 0, 0) self.current_albumart = '' pixmap = QPixmap(PMusic.DEFAULT_IMG) self.img_label = PImage(self, pixmap) self.img_label.resize(self.width(), self.height()) self.img_label.clicked.connect(self.onclick_img_label) self.buttonbar = PButtonBar(self) self.buttonbar.hide() # position: at the bottom self.buttonbar.move(0, self.height() - self.buttonbar.height()) self.buttonbar.clicked_left.connect(self.onclick_prev) self.buttonbar.clicked_mid.connect(self.onclick_main) self.buttonbar.clicked_right.connect(self.onclick_next) # toggle button for shuffle self.shufflebutton = QPushButton(self) self.shufflebutton.hide() self.shufflebutton.setCheckable(True) self.shufflebutton.setText('S') # position: top left corner button_size = int(self.width() * 0.2) self.shufflebutton.setGeometry(0, 0, button_size, button_size) self.shufflebutton.clicked.connect(self.onclick_shuffle) self.quitbutton = QPushButton(self) self.quitbutton.hide() self.quitbutton.setStyleSheet('color: rgb(240, 0, 0)') # red self.quitbutton.setFont(QFont('webdings', 10)) self.quitbutton.setText('r') # cross # position: top right corner self.quitbutton.setGeometry(self.width() - button_size, 0, button_size, button_size) self.quitbutton.clicked.connect(self.onclick_quit) self.show() def enterEvent(self, event): '''on mouse enter, show the buttons''' super().enterEvent(event) self.buttonbar.show() self.shufflebutton.show() self.quitbutton.show() def leaveEvent(self, event): '''on mouse leave, hide the buttons''' super().leaveEvent(event) self.buttonbar.hide() self.shufflebutton.hide() self.quitbutton.hide() @pyqtSlot() def onclick_shuffle(self): '''shuffle button was toggled''' if self.shufflebutton.isChecked(): debug('shuffle: on') self.playlist.setPlaybackMode(QMediaPlaylist.Random) else: debug('shuffle: off') self.playlist.setPlaybackMode(QMediaPlaylist.Loop) @pyqtSlot() def onclick_quit(self): '''quit button was clicked''' debug('quit') self.stop() self.parent().close() @pyqtSlot() def onclick_img_label(self): '''image label was clicked''' debug('onclick_img_label') self.pause() @pyqtSlot() def onclick_prev(self): '''back button was pressed''' debug('onclick_prev') self.playlist.previous() if self.player.state() != QMediaPlayer.PlayingState: debug('player.state == {}'.format(self.player.state())) self.play() @pyqtSlot() def onclick_next(self): '''next button was pressed''' debug('onclick_next') self.playlist.next() if self.player.state() != QMediaPlayer.PlayingState: debug('player.state == {}'.format(self.player.state())) self.play() @pyqtSlot() def onclick_main(self): '''main button was pressed''' debug('onclick_main') # bring up directory selection dialog # have a preference for $HOME/Music/ try: homedir = os.environ['HOME'] if not os.path.isdir(homedir): homedir = os.path.curdir except KeyError: homedir = os.path.curdir music_dir = os.path.join(homedir, 'Music') if not os.path.isdir(music_dir): music_dir = os.path.curdir path = QFileDialog.getExistingDirectory(self, 'Select directory', music_dir, QFileDialog.ShowDirsOnly) debug('path == [{}]'.format(path)) if not path: # cancel return self.stop() self.load_playlist(path) self.play() def onmedia_status_changed(self): '''media changed; player switched to next song''' debug('onmedia_status_changed') debug('player.state == {}'.format(self.player.state())) debug('player.mediastate == {}'.format(self.player.mediaStatus())) # we want to load albumart if the song is in another directory # and display filename on stdout or console log # this is only relevant if the QMediaPlayer is now loading new media if self.player.mediaStatus() == QMediaPlayer.LoadingMedia: media = self.player.currentMedia() if media.isNull(): debug('media isNull') return filename = media.canonicalUrl().path() debug('current media == [{}]'.format(filename)) # make a short path for informational message short_path = filename try: homedir = os.environ['HOME'] + os.path.sep if short_path.startswith(homedir): short_path = filename[len(homedir):] except KeyError: pass if short_path.startswith('Music/'): short_path = short_path[len('Music/'):] print('now playing: {}'.format(short_path)) folder = os.path.dirname(filename) self.load_albumart(folder) elif self.player.mediaStatus() == QMediaPlayer.NoMedia: debug('no media present, change albumart to default image') # change to default image pixmap = QPixmap(PMusic.DEFAULT_IMG) self.img_label.setPixmap(pixmap) self.current_albumart = '' def load_playlist(self, path): '''load new playlist''' debug('load playlist') self.playlist.clear() # Note: not actually sure these formats are all supported ... files = QDirIterator(path, ['*.mp3', '*.ogg', '*.wav', '*.flac'], flags=QDirIterator.Subdirectories) while files.hasNext(): filename = files.next() debug('+ {}'.format(filename)) url = QUrl.fromLocalFile(filename) if not self.playlist.addMedia(QMediaContent(url)): debug('addMedia() => False') self.player.setPlaylist(self.playlist) def load_albumart(self, path): '''load album art''' debug('load albumart, path == {}'.format(path)) # load album art found = False for name in ('cover.jpg', 'Folder.jpg', 'folder.jpg', 'cover.png', 'AlbumArt.jpg', 'AlbumArtSmall.jpg'): filename = os.path.join(path, name) if os.path.isfile(filename): found = True if filename == self.current_albumart: debug('same albumart, already loaded') break debug('loading albumart {}'.format(filename)) pixmap = QPixmap(filename) self.img_label.setPixmap(pixmap) self.current_albumart = filename break if not found: if not self.current_albumart: debug('no albumart found, keeping default image') else: # put default image debug('no albumart found, putting default image') pixmap = QPixmap(PMusic.DEFAULT_IMG) self.img_label.setPixmap(pixmap) self.current_albumart = '' def stop(self): '''stop playing''' debug('stop') self.player.stop() def play(self): '''start playing''' debug('play()') self.player.play() def pause(self): '''pause playing''' if self.player.state() == QMediaPlayer.PlayingState: debug('pause') self.player.pause() elif self.player.state() in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.player.play()
class MusicPlayer(QMainWindow): """MusicPlayer houses all of elements that directly interact with the main window.""" def __init__(self, parent=None): """Initialize the QMainWindow widget. The window title, window icon, and window size are initialized here as well as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar, QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and QVBoxLayout. The connect signals for relavant widgets are also initialized. """ super(MusicPlayer, self).__init__(parent) self.setWindowTitle('Mosaic') window_icon = utilities.resource_filename('mosaic.images', 'icon.png') self.setWindowIcon(QIcon(window_icon)) self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) # Initiates Qt objects to be used by MusicPlayer self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist_location = defaults.Settings().playlist_path self.content = QMediaContent() self.menu = self.menuBar() self.toolbar = QToolBar() self.art = QLabel() self.pixmap = QPixmap() self.slider = QSlider(Qt.Horizontal) self.duration_label = QLabel() self.playlist_dock = QDockWidget('Playlist', self) self.library_dock = QDockWidget('Media Library', self) self.playlist_view = QListWidget() self.library_view = library.MediaLibraryView() self.library_model = library.MediaLibraryModel() self.preferences = configuration.PreferencesDialog() self.widget = QWidget() self.layout = QVBoxLayout(self.widget) self.duration = 0 self.playlist_dock_state = None self.library_dock_state = None # Sets QWidget() as the central widget of the main window self.setCentralWidget(self.widget) self.layout.setContentsMargins(0, 0, 0, 0) self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # Initiates the playlist dock widget and the library dock widget self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock) self.playlist_dock.setWidget(self.playlist_view) self.playlist_dock.setVisible(defaults.Settings().playlist_on_start) self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable) self.addDockWidget(defaults.Settings().dock_position, self.library_dock) self.library_dock.setWidget(self.library_view) self.library_dock.setVisible(defaults.Settings().media_library_on_start) self.library_dock.setFeatures(QDockWidget.DockWidgetClosable) self.tabifyDockWidget(self.playlist_dock, self.library_dock) # Sets the range of the playback slider and sets the playback mode as looping self.slider.setRange(0, self.player.duration() / 1000) self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) # OSX system menu bar causes conflicts with PyQt5 menu bar if sys.platform == 'darwin': self.menu.setNativeMenuBar(False) # Initiates Settings in the defaults module to give access to settings.toml defaults.Settings() # Signals that connect to other methods when they're called self.player.metaDataChanged.connect(self.display_meta_data) self.slider.sliderMoved.connect(self.seek) self.player.durationChanged.connect(self.song_duration) self.player.positionChanged.connect(self.song_position) self.player.stateChanged.connect(self.set_state) self.playlist_view.itemActivated.connect(self.activate_playlist_item) self.library_view.activated.connect(self.open_media_library) self.playlist.currentIndexChanged.connect(self.change_index) self.playlist.mediaInserted.connect(self.initialize_playlist) self.playlist_dock.visibilityChanged.connect(self.dock_visiblity_change) self.library_dock.visibilityChanged.connect(self.dock_visiblity_change) self.preferences.dialog_media_library.media_library_line.textChanged.connect(self.change_media_library_path) self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(self.change_window_size) self.art.mousePressEvent = self.press_playback # Creating the menu controls, media controls, and window size of the music player self.menu_controls() self.media_controls() self.load_saved_playlist() def menu_controls(self): """Initiate the menu bar and add it to the QMainWindow widget.""" self.file = self.menu.addMenu('File') self.edit = self.menu.addMenu('Edit') self.playback = self.menu.addMenu('Playback') self.view = self.menu.addMenu('View') self.help_ = self.menu.addMenu('Help') self.file_menu() self.edit_menu() self.playback_menu() self.view_menu() self.help_menu() def media_controls(self): """Create the bottom toolbar and controls used for media playback.""" self.addToolBar(Qt.BottomToolBarArea, self.toolbar) self.toolbar.setMovable(False) play_icon = utilities.resource_filename('mosaic.images', 'md_play.png') self.play_action = QAction(QIcon(play_icon), 'Play', self) self.play_action.triggered.connect(self.player.play) stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png') self.stop_action = QAction(QIcon(stop_icon), 'Stop', self) self.stop_action.triggered.connect(self.player.stop) previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png') self.previous_action = QAction(QIcon(previous_icon), 'Previous', self) self.previous_action.triggered.connect(self.previous) next_icon = utilities.resource_filename('mosaic.images', 'md_next.png') self.next_action = QAction(QIcon(next_icon), 'Next', self) self.next_action.triggered.connect(self.playlist.next) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self) self.repeat_action.setShortcut('R') self.repeat_action.triggered.connect(self.repeat_song) self.toolbar.addAction(self.play_action) self.toolbar.addAction(self.stop_action) self.toolbar.addAction(self.previous_action) self.toolbar.addAction(self.next_action) self.toolbar.addAction(self.repeat_action) self.toolbar.addWidget(self.slider) self.toolbar.addWidget(self.duration_label) def file_menu(self): """Add a file menu to the menu bar. The file menu houses the Open File, Open Multiple Files, Open Playlist, Open Directory, and Exit Application menu items. """ self.open_action = QAction('Open File', self) self.open_action.setShortcut('O') self.open_action.triggered.connect(self.open_file) self.open_multiple_files_action = QAction('Open Multiple Files', self) self.open_multiple_files_action.setShortcut('M') self.open_multiple_files_action.triggered.connect(self.open_multiple_files) self.open_playlist_action = QAction('Open Playlist', self) self.open_playlist_action.setShortcut('CTRL+P') self.open_playlist_action.triggered.connect(self.open_playlist) self.open_directory_action = QAction('Open Directory', self) self.open_directory_action.setShortcut('D') self.open_directory_action.triggered.connect(self.open_directory) self.save_playlist_action = QAction('Save Playlist', self) self.save_playlist_action.setShortcut('CTRL+S') self.save_playlist_action.triggered.connect(self.save_playlist) self.exit_action = QAction('Quit', self) self.exit_action.setShortcut('CTRL+Q') self.exit_action.triggered.connect(self.closeEvent) self.file.addAction(self.open_action) self.file.addAction(self.open_multiple_files_action) self.file.addAction(self.open_playlist_action) self.file.addAction(self.open_directory_action) self.file.addSeparator() self.file.addAction(self.save_playlist_action) self.file.addSeparator() self.file.addAction(self.exit_action) def edit_menu(self): """Add an edit menu to the menu bar. The edit menu houses the preferences item that opens a preferences dialog that allows the user to customize features of the music player. """ self.preferences_action = QAction('Preferences', self) self.preferences_action.setShortcut('CTRL+SHIFT+P') self.preferences_action.triggered.connect(lambda: self.preferences.exec_()) self.edit.addAction(self.preferences_action) def playback_menu(self): """Add a playback menu to the menu bar. The playback menu houses """ self.play_playback_action = QAction('Play', self) self.play_playback_action.setShortcut('P') self.play_playback_action.triggered.connect(self.player.play) self.stop_playback_action = QAction('Stop', self) self.stop_playback_action.setShortcut('S') self.stop_playback_action.triggered.connect(self.player.stop) self.previous_playback_action = QAction('Previous', self) self.previous_playback_action.setShortcut('B') self.previous_playback_action.triggered.connect(self.previous) self.next_playback_action = QAction('Next', self) self.next_playback_action.setShortcut('N') self.next_playback_action.triggered.connect(self.playlist.next) self.playback.addAction(self.play_playback_action) self.playback.addAction(self.stop_playback_action) self.playback.addAction(self.previous_playback_action) self.playback.addAction(self.next_playback_action) def view_menu(self): """Add a view menu to the menu bar. The view menu houses the Playlist, Media Library, Minimalist View, and Media Information menu items. The Playlist item toggles the playlist dock into and out of view. The Media Library items toggles the media library dock into and out of view. The Minimalist View item resizes the window and shows only the menu bar and player controls. The Media Information item opens a dialog that shows information relevant to the currently playing song. """ self.dock_action = self.playlist_dock.toggleViewAction() self.dock_action.setShortcut('CTRL+ALT+P') self.library_dock_action = self.library_dock.toggleViewAction() self.library_dock_action.setShortcut('CTRL+ALT+L') self.minimalist_view_action = QAction('Minimalist View', self) self.minimalist_view_action.setShortcut('CTRL+ALT+M') self.minimalist_view_action.setCheckable(True) self.minimalist_view_action.triggered.connect(self.minimalist_view) self.view_media_info_action = QAction('Media Information', self) self.view_media_info_action.setShortcut('CTRL+SHIFT+M') self.view_media_info_action.triggered.connect(self.media_information_dialog) self.view.addAction(self.dock_action) self.view.addAction(self.library_dock_action) self.view.addSeparator() self.view.addAction(self.minimalist_view_action) self.view.addSeparator() self.view.addAction(self.view_media_info_action) def help_menu(self): """Add a help menu to the menu bar. The help menu houses the about dialog that shows the user information related to the application. """ self.about_action = QAction('About', self) self.about_action.setShortcut('H') self.about_action.triggered.connect(lambda: about.AboutDialog().exec_()) self.help_.addAction(self.about_action) def open_file(self): """Open the selected file and add it to a new playlist.""" filename, success = QFileDialog.getOpenFileName(self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly) if success: file_info = QFileInfo(filename).fileName() playlist_item = QListWidgetItem(file_info) self.playlist.clear() self.playlist_view.clear() self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(filename))) self.player.setPlaylist(self.playlist) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def open_multiple_files(self): """Open the selected files and add them to a new playlist.""" filenames, success = QFileDialog.getOpenFileNames(self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly) if success: self.playlist.clear() self.playlist_view.clear() for file in natsort.natsorted(filenames, alg=natsort.ns.PATH): file_info = QFileInfo(file).fileName() playlist_item = QListWidgetItem(file_info) self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file))) self.player.setPlaylist(self.playlist) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def open_playlist(self): """Load an M3U or PLS file into a new playlist.""" playlist, success = QFileDialog.getOpenFileName(self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly) if success: playlist = QUrl.fromLocalFile(playlist) self.playlist.clear() self.playlist_view.clear() self.playlist.load(playlist) self.player.setPlaylist(self.playlist) for song_index in range(self.playlist.mediaCount()): file_info = self.playlist.media(song_index).canonicalUrl().fileName() playlist_item = QListWidgetItem(file_info) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def save_playlist(self): """Save the media in the playlist dock as a new M3U playlist.""" playlist, success = QFileDialog.getSaveFileName(self, 'Save Playlist', '', 'Playlist (*.m3u)', '') if success: saved_playlist = "{}.m3u" .format(playlist) self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u") def load_saved_playlist(self): """Load the saved playlist if user setting permits.""" saved_playlist = "{}/.m3u" .format(self.playlist_location) if os.path.exists(saved_playlist): playlist = QUrl().fromLocalFile(saved_playlist) self.playlist.load(playlist) self.player.setPlaylist(self.playlist) for song_index in range(self.playlist.mediaCount()): file_info = self.playlist.media(song_index).canonicalUrl().fileName() playlist_item = QListWidgetItem(file_info) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) def open_directory(self): """Open the selected directory and add the files within to an empty playlist.""" directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly) if directory: self.playlist.clear() self.playlist_view.clear() for dirpath, __, files in os.walk(directory): for filename in natsort.natsorted(files, alg=natsort.ns.PATH): file = os.path.join(dirpath, filename) if filename.endswith(('mp3', 'flac')): self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file))) playlist_item = QListWidgetItem(filename) playlist_item.setToolTip(filename) self.playlist_view.addItem(playlist_item) self.player.setPlaylist(self.playlist) self.playlist_view.setCurrentRow(0) self.player.play() def open_media_library(self, index): """Open a directory or file from the media library into an empty playlist.""" self.playlist.clear() self.playlist_view.clear() if self.library_model.fileName(index).endswith(('mp3', 'flac')): self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(self.library_model.filePath(index)))) self.playlist_view.addItem(self.library_model.fileName(index)) elif self.library_model.isDir(index): directory = self.library_model.filePath(index) for dirpath, __, files in os.walk(directory): for filename in natsort.natsorted(files, alg=natsort.ns.PATH): file = os.path.join(dirpath, filename) if filename.endswith(('mp3', 'flac')): self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file))) playlist_item = QListWidgetItem(filename) playlist_item.setToolTip(filename) self.playlist_view.addItem(playlist_item) self.player.setPlaylist(self.playlist) self.player.play() def display_meta_data(self): """Display the current song's metadata in the main window. If the current song contains metadata, its cover art is extracted and shown in the main window while the track number, artist, album, and track title are shown in the window title. """ if self.player.isMetaDataAvailable(): file_path = self.player.currentMedia().canonicalUrl().toLocalFile() (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path) try: self.pixmap.loadFromData(artwork) except TypeError: self.pixmap = QPixmap(artwork) meta_data = '{} - {} - {} - {}' .format(track_number, artist, album, title) self.setWindowTitle(meta_data) self.art.setScaledContents(True) self.art.setPixmap(self.pixmap) self.layout.addWidget(self.art) def initialize_playlist(self, start): """Display playlist and reset playback mode when media inserted into playlist.""" if start == 0: if self.library_dock.isVisible(): self.playlist_dock.setVisible(True) self.playlist_dock.show() self.playlist_dock.raise_() if self.playlist.playbackMode() != QMediaPlaylist.Sequential: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action.setIcon(QIcon(repeat_icon)) def press_playback(self, event): """Change the playback of the player on cover art mouse event. When the cover art is clicked, the player will play the media if the player is either paused or stopped. If the media is playing, the media is set to pause. """ if event.button() == 1 and configuration.Playback().cover_art_playback.isChecked(): if (self.player.state() == QMediaPlayer.StoppedState or self.player.state() == QMediaPlayer.PausedState): self.player.play() elif self.player.state() == QMediaPlayer.PlayingState: self.player.pause() def seek(self, seconds): """Set the position of the song to the position dragged to by the user.""" self.player.setPosition(seconds * 1000) def song_duration(self, duration): """Set the slider to the duration of the currently played media.""" duration /= 1000 self.duration = duration self.slider.setMaximum(duration) def song_position(self, progress): """Move the horizontal slider in sync with the duration of the song. The progress is relayed to update_duration() in order to display the time label next to the slider. """ progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.update_duration(progress) def update_duration(self, current_duration): """Calculate the time played and the length of the song. Both of these times are sent to duration_label() in order to display the times on the toolbar. """ duration = self.duration if current_duration or duration: time_played = QTime((current_duration / 3600) % 60, (current_duration / 60) % 60, (current_duration % 60), (current_duration * 1000) % 1000) song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60), (duration * 1000) % 1000) if duration > 3600: time_format = "hh:mm:ss" else: time_format = "mm:ss" time_display = "{} / {}" .format(time_played.toString(time_format), song_length.toString(time_format)) else: time_display = "" self.duration_label.setText(time_display) def set_state(self, state): """Change the icon in the toolbar in relation to the state of the player. The play icon changes to the pause icon when a song is playing and the pause icon changes back to the play icon when either paused or stopped. """ if self.player.state() == QMediaPlayer.PlayingState: pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png') self.play_action.setIcon(QIcon(pause_icon)) self.play_action.triggered.connect(self.player.pause) elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState): self.play_action.triggered.connect(self.player.play) play_icon = utilities.resource_filename('mosaic.images', 'md_play.png') self.play_action.setIcon(QIcon(play_icon)) def previous(self): """Move to the previous song in the playlist. Moves to the previous song in the playlist if the current song is less than five seconds in. Otherwise, restarts the current song. """ if self.player.position() <= 5000: self.playlist.previous() else: self.player.setPosition(0) def repeat_song(self): """Set the current media to repeat and change the repeat icon accordingly. There are four playback modes: repeat none, repeat all, repeat once, and shuffle. Clicking the repeat button cycles through each playback mode. """ if self.playlist.playbackMode() == QMediaPlaylist.Sequential: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_all.png') self.repeat_action.setIcon(QIcon(repeat_on_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.Loop: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_once.png') self.repeat_action.setIcon(QIcon(repeat_on_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop: self.playlist.setPlaybackMode(QMediaPlaylist.Random) repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png') self.repeat_action.setIcon(QIcon(repeat_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.Random: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action.setIcon(QIcon(repeat_icon)) def activate_playlist_item(self, item): """Set the active media to the playlist item dobule-clicked on by the user.""" current_index = self.playlist_view.row(item) if self.playlist.currentIndex() != current_index: self.playlist.setCurrentIndex(current_index) if self.player.state() != QMediaPlayer.PlayingState: self.player.play() def change_index(self, row): """Highlight the row in the playlist of the active media.""" self.playlist_view.setCurrentRow(row) def minimalist_view(self): """Resize the window to only show the menu bar and audio controls.""" if self.minimalist_view_action.isChecked(): if self.playlist_dock.isVisible(): self.playlist_dock_state = True if self.library_dock.isVisible(): self.library_dock_state = True self.library_dock.close() self.playlist_dock.close() QTimer.singleShot(10, lambda: self.resize(500, 0)) else: self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) if self.library_dock_state: self.library_dock.setVisible(True) if self.playlist_dock_state: self.playlist_dock.setVisible(True) def dock_visiblity_change(self, visible): """Change the size of the main window when the docks are toggled.""" if visible and self.playlist_dock.isVisible() and not self.library_dock.isVisible(): self.resize(defaults.Settings().window_size + self.playlist_dock.width() + 6, self.height()) elif visible and not self.playlist_dock.isVisible() and self.library_dock.isVisible(): self.resize(defaults.Settings().window_size + self.library_dock.width() + 6, self.height()) elif visible and self.playlist_dock.isVisible() and self.library_dock.isVisible(): self.resize(defaults.Settings().window_size + self.library_dock.width() + 6, self.height()) elif (not visible and not self.playlist_dock.isVisible() and not self.library_dock.isVisible()): self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) def media_information_dialog(self): """Show a dialog of the current song's metadata.""" if self.player.isMetaDataAvailable(): file_path = self.player.currentMedia().canonicalUrl().toLocalFile() else: file_path = None dialog = information.InformationDialog(file_path) dialog.exec_() def change_window_size(self): """Change the window size of the music player.""" self.playlist_dock.close() self.library_dock.close() self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) def change_media_library_path(self, path): """Change the media library path to the new path selected in the preferences dialog.""" self.library_model.setRootPath(path) self.library_view.setModel(self.library_model) self.library_view.setRootIndex(self.library_model.index(path)) def closeEvent(self, event): """Override the PyQt close event in order to handle save playlist on close.""" playlist = "{}/.m3u" .format(self.playlist_location) if defaults.Settings().save_playlist_on_close: self.playlist.save(QUrl().fromLocalFile(playlist), "m3u") else: if os.path.exists(playlist): os.remove(playlist) QApplication.quit()
class music_play(QtWidgets.QMainWindow, Ui_Form): #初始化一些操作 def __init__(self): super(music_play, self).__init__() #调用该类的父类的初始化函数,完成窗口布局操作 self.setupUi(self) self.setWindowTitle("VIP音乐播放器") self.setWindowIcon(QIcon("format.ico")) #self.SaveData = db() self.m_filepath = 'E:/MusicMedia/MusicMedia/music/' self.player = QMediaPlayer() self.PlayList = QMediaPlaylist() self.player.setPlaylist(self.PlayList) #网络歌曲的搜索模块 def start_search(self): music_name = self.SongName.text() musician_name = self.Musician.text() search = search_song(self.music_name, self.musician_name) search.song.connect(self.search_song2) search_song.start() def search_song2(self, music_data): #music_data = self.SaveData.get_data(musician_name,music_name) #在此处构建一个url实现在线播放 print(music_data) file_url = music_data[2] file_name = "{} - {}".format(music_data[0], music_data[1]) self.down_music(file_url, file_name) self.Internet.addItem(file_name) #当地歌曲的加载模块 def Load_Song(self): self.PlayList.clear() #便于网络歌曲加入 self.Local.clear() #刷新播放列表 list = os.listdir(self.m_filepath) for cur_music in list: self.Local.addItem(cur_music) self.PlayList.addMedia( QMediaContent(QUrl.fromLocalFile(self.m_filepath + cur_music))) #在线歌曲下载模块 def down_music(self, url, name): header = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36', } response = requests.get(url, headers=header) with open("{}/{}.mp3".format(self.m_filepath, name), "wb") as file: file.write(response.content) #用户自定义歌曲模块 def custom_current_music(self): cur_music = self.Local.currentItem().text() self.CurMusic.setText(cur_music) item = self.Local.currentRow() self.PlayList.setCurrentIndex(item) self.player.stop() #停止上一首歌 self.player.play() #开始播放当前指定的歌曲 #设置音乐播放模式模块 def music_Mode(self): self.PlayList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) #单曲循环 self.PlayList.setPlaybackMode(QMediaPlaylist.Random) # 随机播放 self.PlayList.setPlaybackMode(QMediaPlaylist.Sequential) # 顺序播放 #重写窗口paintEvent函数 def paintEvent(self, event): painter = QPainter(self) painter.drawPixmap(self.rect(), QPixmap("image/background.jpg"))
class TimerWidget(QWidget): def __init__(self): super().__init__() self.initUI() # Инициализируем плеер и плейлист, на котором поставим цикличное воспроизведение self.playlist = QMediaPlaylist(self) self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.player = QMediaPlayer() # Создадим пустую ссылку, чтобы программа не крашилась, если пользователь не выберет мелодию self.url = QUrl() # Подскажем для чего кнопка self.lbl = QLabel('Выберите мелодию для таймера:', self) self.lbl.move(165, 100) # Кнопка для выбора файла с мелодией self.btn_getfile = QPushButton('Выбрать файл', self) self.btn_getfile.move(200, 125) self.btn_getfile.resize(100, 50) self.btn_getfile.clicked.connect(self.getfile) # Кнопка старта таймера self.btn_start = QPushButton('Старт', self) self.btn_start.move(225, 225) self.btn_start.resize(50, 50) self.btn_start.clicked.connect(self.start_timer) # Кнопка остановки таймера до того, как он закончит отсчет self.btn_stop = QPushButton('Стоп', self) self.btn_stop.move(250, 225) self.btn_stop.resize(50, 50) self.btn_stop.clicked.connect(self.stop_timer) self.btn_stop.setVisible(False) # Кнопка паузы таймера self.btn_pause = QPushButton('Пауза', self) self.btn_pause.move(200, 225) self.btn_pause.resize(50, 50) self.btn_pause.clicked.connect(self.pause_timer) self.btn_pause.setVisible(False) # Кнопка для продолжения отсчета таймера self.btn_continue = QPushButton('Дальше', self) self.btn_continue.move(200, 225) self.btn_continue.resize(50, 50) self.btn_continue.clicked.connect(self.continue_timer) self.btn_continue.setVisible(False) # Кнопка для выключения таймера, когда он закончит отсчет self.btn_off = QPushButton('Выкл', self) self.btn_off.move(225, 225) self.btn_off.resize(50, 50) self.btn_off.clicked.connect(self.timer_off) self.btn_off.setVisible(False) # Спрашивваем значение таймера self.get_timer = QTimeEdit(self) self.get_timer.move(185, 175) self.get_timer.resize(130, 50) self.get_timer.setFont(QFont('Times', 15, QFont.Bold)) self.get_timer.setDisplayFormat('HH:mm:ss') # Дисплей для вывода таймера self.dsp = QLCDNumber(self) self.dsp.resize(200, 50) self.dsp.move(150, 175) self.dsp.setVisible(False) self.dsp.setDigitCount(8) # Таймер self.nTimer = QTimer() self.nTimer.timeout.connect(self.timer) def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Таймер') def start_timer(self): # Добавляем мелодию в плеер self.content = QMediaContent(self.url) self.playlist.addMedia(self.content) self.player.setPlaylist(self.playlist) # Выводим начальное значение времени на дисплей self.dsp.display(self.get_timer.time().toString('hh:mm:ss')) # Переводим время в секунды timer = self.get_timer.time() timer_text = timer.toString('hh:mm:ss') timer_int = list(map(lambda x: int(x), timer_text.split(':'))) self.timer_in_sec = timer_int[0]*3600 + timer_int[1]*60 + timer_int[2] # Проверяем не установили ли нулевое значение if self.timer_in_sec == 0: self.timer_timeout() else: # Запускаем таймер self.nTimer.start(1000) # Махинации с показом кнопок self.btn_start.setVisible(False) self.btn_pause.setVisible(True) self.btn_stop.setVisible(True) self.dsp.setVisible(True) self.get_timer.setVisible(False) self.lbl.setVisible(False) self.btn_getfile.setVisible(False) def timer(self): # Функция обновления таймера и дисплея со временем # Делаем обратный отсчет, отнимая каждую секунду единицу из начального значения self.timer_in_sec -= 1 # Переводим целочисленные значения в строку timer_text = list(map(lambda x: str(x), [self.timer_in_sec // 3600, (self.timer_in_sec % 3600) // 60, (self.timer_in_sec % 3600) % 60])) # Если один символ, то к нему добавляется ноль if len(timer_text[0]) == 1: timer_text[0] = '0' + timer_text[0] if len(timer_text[1]) == 1: timer_text[1] = '0' + timer_text[1] if len(timer_text[2]) == 1: timer_text[2] = '0' + timer_text[2] # Объединяем список в формат hh:mm:ss timer_text = ':'.join(timer_text) # Выводим текст со временем на дисплей self.dsp.display(timer_text) # Если таймер дошел до нуля: if self.timer_in_sec == 0: self.timer_timeout() else: # Обновляем таймер self.nTimer.start(1000) def stop_timer(self): # Останавливаем таймер self.nTimer.stop() # Махинации с кнопками self.btn_start.setVisible(True) self.btn_stop.setVisible(False) self.btn_pause.setVisible(False) self.dsp.setVisible(False) self.btn_continue.setVisible(False) self.get_timer.setVisible(True) self.btn_getfile.setVisible(True) self.lbl.setVisible(True) def continue_timer(self): # Продолжаем таймер с того места, где остановились self.nTimer.start(self.inter) # Махинации с показом кнопок self.btn_continue.setVisible(False) self.btn_pause.setVisible(True) def pause_timer(self): # Ловим оставшееся время таймера self.inter = self.nTimer.remainingTime() # Останавливаем таймер и делаем махинации с показом кнопок self.nTimer.stop() self.btn_pause.setVisible(False) self.btn_continue.setVisible(True) def timer_off(self): # Махинации с кнопками self.btn_start.setVisible(True) self.dsp.setVisible(False) self.get_timer.setVisible(True) self.btn_off.setVisible(False) self.btn_getfile.setVisible(True) self.lbl.setVisible(True) # Останавливаем мелодию self.player.stop() def timer_timeout(self): # Останавливаем таймер self.nTimer.stop() # Махинации с кнопками self.get_timer.setVisible(False) self.btn_stop.setVisible(False) self.btn_pause.setVisible(False) self.btn_continue.setVisible(False) self.btn_off.setVisible(True) self.dsp.setVisible(True) self.lbl.setVisible(False) self.btn_getfile.setVisible(False) # Запускаем функцию воспроизведения мелодии self.playmus() def playmus(self): # Воспроизводим мелодию self.player.play() def getfile(self): # Достаем файл с мелодией и сохраняем её путь fname = QFileDialog.getOpenFileName(self, 'Open File', '/home', 'Audio Files (*mp3 *wav)') self.url = QUrl.fromLocalFile(fname[0])
class MainWindow(QMainWindow): def __init__(self, audio_file_name: str): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.icon_alarm_clock = QIcon(str(DIR_ICONS / 'alarm-clock.png')) self.setWindowIcon(self.icon_alarm_clock) self.tray = QSystemTrayIcon(self.icon_alarm_clock) self.tray.setToolTip(self.windowTitle()) self.tray.activated.connect(self._on_tray_activated) self.tray.show() self.read_settings() self._button_group = QButtonGroup() self._button_group.addButton(self.ui.at_time_rb) self._button_group.addButton(self.ui.through_time_rb) self._button_group.buttonClicked.connect(self._update_states) self.ui.start_stop.clicked.connect(self._start_stop) self.ui.more_sleep.clicked.connect(self._more_sleep) self.ui.i_woke_up.clicked.connect(self._i_woke_up) self._timer = QTimer() self._timer.setInterval(100) self._timer.timeout.connect(self._tick) self._timer_inc_volume = QTimer() self._timer_inc_volume.setInterval(500) self._timer_inc_volume.timeout.connect(self._inc_volume_tick) self._woke_up = False self._alarm_time: QTime = None self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) url = QUrl.fromLocalFile(audio_file_name) self.playlist.addMedia(QMediaContent(url)) self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self._update_states() def _update_states(self): self.ui.at_time.setEnabled(self.ui.at_time_rb.isChecked()) self.ui.through_time.setEnabled(self.ui.through_time_rb.isChecked()) self.ui.i_woke_up.setVisible(self._woke_up) self.ui.more_sleep.setVisible(self._woke_up) if self._woke_up: self.ui.start_stop.setChecked(False) self.ui.start_stop.setVisible(not self._woke_up) if self.ui.start_stop.isChecked(): self.ui.start_stop.setText('Стоп') else: self.ui.start_stop.setText('Запустить') # Корректируем высоту окна после возможного скрытия кнопок self.resize(self.width(), self.minimumHeight()) def _inc_volume_tick(self): if self.player.volume() >= 100: self._timer_inc_volume.stop() self.player.setVolume(self.player.volume() + 1) def _tick(self): remain = QTime.currentTime().secsTo(self._alarm_time) if remain < 0: remain += 24 * 3600 elif remain == 0: self._woke_up = True self._timer.stop() self._update_states() self.player.setVolume(1) self.player.play() self._timer_inc_volume.start() self._set_visible(True) hh, mm = divmod(remain, 3600) mm, ss = divmod(mm, 60) alarm_str = self._alarm_time.toString('hh:mm:ss') self.ui.time_remaining.setText(f"Звонок в {alarm_str}. Осталось: {hh:0>2}:{mm:0>2}:{ss:0>2}") def _i_woke_up(self): self._woke_up = False self.player.stop() self._update_states() def _start(self): self._woke_up = False if self.ui.at_time_rb.isChecked(): self._alarm_time = self.ui.at_time.time() elif self.ui.through_time_rb.isChecked(): t = self.ui.through_time.time() self._alarm_time = add_to_current_time(t) self._timer.start() self._update_states() def _stop(self): self._woke_up = False self._timer.stop() self._update_states() def _start_stop(self): if self.ui.start_stop.isChecked(): self._start() else: self._stop() def _more_sleep(self): self._i_woke_up() t = self.ui.through_time.time() self._alarm_time = add_to_current_time(t) self._timer.start() self.ui.start_stop.setChecked(True) self._update_states() def _set_visible(self, visible: bool): self.setVisible(visible) if visible: self.showNormal() self.activateWindow() def _on_tray_activated(self, reason): self._set_visible(not self.isVisible()) def changeEvent(self, event: QEvent): if event.type() == QEvent.WindowStateChange: # Если окно свернули if self.isMinimized(): # Прячем окно с панели задач QTimer.singleShot(0, self.hide) def read_settings(self): ini = QSettings(SETTINGS_FILE_NAME, QSettings.IniFormat) if state := ini.value('MainWindow_State'): self.restoreState(state) if geometry := ini.value('MainWindow_Geometry'): self.restoreGeometry(geometry)
class QgsFmvPlayer(QMainWindow, Ui_PlayerWindow): """ Video Player Class """ def __init__(self, iface, path, parent=None, meta_reader=None, pass_time=None, initialPt=None, isStreaming=False): """ Constructor """ super(QgsFmvPlayer, self).__init__(parent) self.setupUi(self) self.parent = parent self.iface = iface self.fileName = path self.initialPt = initialPt self.meta_reader = meta_reader self.isStreaming = isStreaming self.createingMosaic = False self.currentInfo = 0.0 self.data = None # Create Draw Toolbar self.DrawToolBar.addAction(self.actionMagnifying_glass) self.DrawToolBar.addSeparator() # Draw Polygon QToolButton self.toolBtn_DPolygon.setDefaultAction(self.actionDraw_Polygon) self.DrawToolBar.addWidget(self.toolBtn_DPolygon) # Draw Point QToolButton self.toolBtn_DPoint.setDefaultAction(self.actionDraw_Pinpoint) self.DrawToolBar.addWidget(self.toolBtn_DPoint) # Draw Point QToolButton self.toolBtn_DLine.setDefaultAction(self.actionDraw_Line) self.DrawToolBar.addWidget(self.toolBtn_DLine) self.DrawToolBar.addAction(self.actionRuler) self.DrawToolBar.addSeparator() # # Censure QToolButton # self.toolBtn_Cesure.setDefaultAction(self.actionCensure) # self.DrawToolBar.addWidget(self.toolBtn_Cesure) # self.DrawToolBar.addSeparator() # # # Object Tracking # self.DrawToolBar.addAction(self.actionObject_Tracking) self.toolBtn_Cesure.setVisible(False) # Hide Color Button self.btn_Color.hide() self.RecGIF = QMovie(":/imgFMV/images/record.gif") self.videoWidget.customContextMenuRequested[QPoint].connect( self.contextMenuRequested) self.menubarwidget.customContextMenuRequested[QPoint].connect( self.contextMenuBarRequested) self.duration = 0 self.playerMuted = False self.HasFileAudio = False self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.pass_time = pass_time self.player.setNotifyInterval(700) # Metadata Callback Interval self.playlist = QMediaPlaylist() self.player.setVideoOutput( self.videoWidget.videoSurface()) # Abstract Surface self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.stateChanged.connect(self.setCurrentState) self.playerState = QMediaPlayer.LoadingMedia self.playFile(path) self.sliderDuration.setRange(0, self.player.duration() / 1000) self.volumeSlider.setValue(self.player.volume()) self.volumeSlider.enterEvent = self.showVolumeTip self.metadataDlg = QgsFmvMetadata(parent=self, player=self) self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg) self.metadataDlg.setMinimumWidth(500) self.metadataDlg.hide() self.converter = Converter() self.BitratePlot = CreatePlotsBitrate() def HasAudio(self, videoPath): """ Check if video have Metadata or not """ try: p = _spawn([ '-i', videoPath, '-show_streams', '-select_streams', 'a', '-preset', 'ultrafast', '-loglevel', 'error' ], t="probe") stdout_data, _ = p.communicate() if stdout_data == b'': qgsu.showUserAndLogMessage( QCoreApplication.translate( "QgsFmvPlayer", "This video doesn't have Audio ! ")) self.actionAudio.setEnabled(False) self.actionSave_Audio.setEnabled(False) return False return True except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Audio check Failed! : "), str(e)) self.actionAudio.setEnabled(False) self.actionSave_Audio.setEnabled(False) def get_metadata_from_buffer(self, currentTime): """ Metadata CallBack """ try: # There is no way to spawn a thread and call after join() without blocking the video UI thread. # callBackMetadata can be as fast as possible, it will always create a small video lag every time meta are read. # To get rid of this, we fill a buffer (BufferedMetaReader) in the QManager with some Metadata in advance, # and hope they'll be ready to read here in a totaly non-blocking # way (increase the buffer size if needed in QManager). stdout_data = self.meta_reader.get(currentTime) # qgsu.showUserAndLogMessage( # "", "stdout_data: " + str(stdout_data) + " currentTime: " + str(currentTime), onlyLog=True) if stdout_data == 'NOT_READY': self.metadataDlg.menuSave.setEnabled(False) qgsu.showUserAndLogMessage( "", "Buffer value read but is not ready, increase buffer size. : ", onlyLog=True) return #Values need to be read, pause the video a short while elif stdout_data == 'BUFFERING': qgsu.showUserAndLogMessage("Buffering metadata...", "", duration=4, level=QGis.Info) self.player.pause() QTimer.singleShot(2500, lambda: self.player.play()) return elif stdout_data == b'' or len(stdout_data) == 0: self.metadataDlg.menuSave.setEnabled(False) qgsu.showUserAndLogMessage( "", "Buffer returned empty metadata, check pass_time. : ", onlyLog=True) return self.packetStreamParser(stdout_data) except Exception as inst: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Metadata Buffer Failed! : "), str(inst)) def packetStreamParser(self, stdout_data): ''' Common packet process''' for packet in StreamParser(stdout_data): try: if isinstance(packet, UnknownElement): qgsu.showUserAndLogMessage( "Error interpreting klv data, metadata cannot be read.", "the parser did not recognize KLV data", level=QGis.Warning, onlyLog=True) continue data = packet.MetadataList() self.data = data if self.metadataDlg.isVisible( ): # Only add metada to table if this QDockWidget is visible (speed plugin) self.metadataDlg.menuSave.setEnabled(True) self.addMetadata(data) UpdateLayers(packet, parent=self, mosaic=self.createingMosaic) QApplication.processEvents() return except Exception: None # qgsu.showUserAndLogMessage(QCoreApplication.translate( # "QgsFmvPlayer", "Meta update failed! "), " Packet:" + str(packet) + ", error:" + str(inst), level=QGis.Warning) def callBackMetadata(self, currentTime, nextTime): """ Metadata CallBack """ try: port = int(self.fileName.split(':')[2]) t = callBackMetadataThread(cmds=[ '-i', self.fileName.replace(str(port), str( port + 1)), '-ss', currentTime, '-to', nextTime, '-map', 'data-re', '-preset', 'ultrafast', '-f', 'data', '-' ]) t.start() t.join(1) if t.is_alive(): t.p.terminate() t.join() qgsu.showUserAndLogMessage("", "callBackMetadataThread self.stdout: " + str(t.stdout), onlyLog=True) if t.stdout == b'': return self.packetStreamParser(t.stdout) except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Metadata Callback Failed! : "), str(e)) def GetPacketData(self): ''' Return Current Packet data ''' return self.data def addMetadata(self, packet): ''' Add Metadata to List ''' self.clearMetadata() row = 0 for key in sorted(packet.keys()): self.metadataDlg.VManager.insertRow(row) self.metadataDlg.VManager.setItem(row, 0, QTableWidgetItem(str(key))) self.metadataDlg.VManager.setItem( row, 1, QTableWidgetItem(str(packet[key][0]))) self.metadataDlg.VManager.setItem( row, 2, QTableWidgetItem(str(packet[key][1]))) row += 1 self.metadataDlg.VManager.setVisible(False) self.metadataDlg.VManager.resizeColumnsToContents() self.metadataDlg.VManager.setVisible(True) self.metadataDlg.VManager.verticalScrollBar().setSliderPosition( self.sliderPosition) def clearMetadata(self): ''' Clear Metadata List ''' try: self.sliderPosition = self.metadataDlg.VManager.verticalScrollBar( ).sliderPosition() self.metadataDlg.VManager.setRowCount(0) except Exception: None def saveInfoToJson(self): """ Save video Info to json """ out_json, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save Json"), isSave=True, exts="json") if not out_json: return taskSaveInfoToJson = QgsTask.fromFunction( 'Save Video Info to Json Task', self.converter.probeToJson, fname=self.fileName, output=out_json, on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskSaveInfoToJson) return def showVideoInfo(self): ''' Show default probe info ''' taskSaveInfoToJson = QgsTask.fromFunction( 'Show Video Info Task', self.converter.probeShow, fname=self.fileName, on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskSaveInfoToJson) return def state(self): ''' Return Current State ''' return self.playerState def setCurrentState(self, state): ''' Set Current State ''' if state != self.playerState: self.playerState = state if state == QMediaPlayer.StoppedState: self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png")) return def showColorDialog(self): ''' Show Color dialog ''' self.ColorDialog = ColorDialog(parent=self) self.ColorDialog.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint) # Fail if not uncheked self.actionMagnifying_glass.setChecked(False) self.ColorDialog.exec_() QApplication.processEvents() self.ColorDialog.contrastSlider.setValue(80) self.ColorDialog.contrastSlider.triggerAction( QAbstractSlider.SliderMove) return def createMosaic(self, value): ''' Function for create Video Mosaic ''' home = os.path.expanduser("~") qgsu.createFolderByName(home, "QGIS_FMV") homefmv = os.path.join(home, "QGIS_FMV") root, _ = os.path.splitext(os.path.basename(self.fileName)) qgsu.createFolderByName(homefmv, root) self.createingMosaic = value # Create Group CreateGroupByName() return def contextMenuBarRequested(self, point): ''' Context Menu Menu Bar ''' menu = QMenu('ToolBars') toolbars = self.findChildren(QToolBar) for toolbar in toolbars: action = menu.addAction(toolbar.windowTitle()) action.setCheckable(True) action.setChecked(toolbar.isVisible()) action.setObjectName(toolbar.windowTitle()) action.triggered.connect(lambda _: self.ToggleQToolBar()) menu.exec_(self.mapToGlobal(point)) return def ToggleQToolBar(self): ''' Toggle ToolBar ''' toolbars = self.findChildren(QToolBar) for toolbar in toolbars: if self.sender().objectName() == toolbar.windowTitle(): toolbar.toggleViewAction().trigger() def contextMenuRequested(self, point): ''' Context Menu Video ''' menu = QMenu('Video') # actionColors = menu.addAction( # QCoreApplication.translate("QgsFmvPlayer", "Color Options")) # actionColors.setShortcut("Ctrl+May+C") # actionColors.triggered.connect(self.showColorDialog) actionMute = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Mute/Unmute")) actionMute.setShortcut("Ctrl+Shift+U") actionMute.triggered.connect(self.setMuted) menu.addSeparator() actionAllFrames = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Extract All Frames")) actionAllFrames.setShortcut("Ctrl+Shift+A") actionAllFrames.triggered.connect(self.ExtractAllFrames) actionCurrentFrames = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Extract Current Frame")) actionCurrentFrames.setShortcut("Ctrl+Shift+Q") actionCurrentFrames.triggered.connect(self.ExtractCurrentFrame) menu.addSeparator() actionShowMetadata = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Show Metadata")) actionShowMetadata.setShortcut("Ctrl+Shift+M") actionShowMetadata.triggered.connect(self.OpenQgsFmvMetadata) menu.exec_(self.mapToGlobal(point)) # Start Snnipet FILTERS def grayFilter(self, value): ''' Gray Video Filter ''' self.UncheckFilters(self.sender(), value) self.videoWidget.SetGray(value) self.videoWidget.UpdateSurface() return def MirrorHorizontalFilter(self, value): ''' Mirror Horizontal Video Filter ''' self.UncheckFilters(self.sender(), value) self.videoWidget.SetMirrorH(value) self.videoWidget.UpdateSurface() return def edgeFilter(self, value): ''' Edge Detection Video Filter ''' self.UncheckFilters(self.sender(), value) self.videoWidget.SetEdgeDetection(value) self.videoWidget.UpdateSurface() return def invertColorFilter(self, value): ''' Invert Color Video Filter ''' self.UncheckFilters(self.sender(), value) self.videoWidget.SetInvertColor(value) self.videoWidget.UpdateSurface() return def autoContrastFilter(self, value): ''' Auto Contrast Video Filter ''' self.UncheckFilters(self.sender(), value) self.videoWidget.SetAutoContrastFilter(value) self.videoWidget.UpdateSurface() return def monoFilter(self, value): ''' Filter Mono Video ''' self.UncheckFilters(self.sender(), value) self.videoWidget.SetMonoFilter(value) self.videoWidget.UpdateSurface() return def magnifier(self, value): ''' Magnifier Glass Utils ''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetMagnifier(value) self.videoWidget.UpdateSurface() return def pointDrawer(self, value): ''' Draw Point ''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetPointDrawer(value) self.videoWidget.UpdateSurface() def lineDrawer(self, value): ''' Draw Line ''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetLineDrawer(value) self.videoWidget.UpdateSurface() def polygonDrawer(self, value): ''' Draw Polygon ''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetPolygonDrawer(value) self.videoWidget.UpdateSurface() def ojectTracking(self, value): ''' Object Tracking ''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetObjectTracking(value) self.videoWidget.UpdateSurface() def VideoRuler(self, value): ''' Video Ruler ''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetRuler(value) if value: self.player.pause() self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png")) else: self.videoWidget.ResetDrawRuler() self.player.play() self.btn_play.setIcon(QIcon(":/imgFMV/images/pause.png")) self.videoWidget.UpdateSurface() def VideoCensure(self, value): ''' Censure Video Parts''' self.UncheckUtils(self.sender(), value) self.videoWidget.SetCensure(value) self.videoWidget.UpdateSurface() return def UncheckUtils(self, sender, value): ''' Uncheck Utils Video ''' self.actionMagnifying_glass.setChecked(False) self.actionDraw_Pinpoint.setChecked(False) self.actionDraw_Line.setChecked(False) self.actionDraw_Polygon.setChecked(False) self.actionObject_Tracking.setChecked(False) self.actionRuler.setChecked(False) self.actionCensure.setChecked(False) self.videoWidget.RestoreDrawer() sender.setChecked(value) return def UncheckFilters(self, sender, value): ''' Uncheck Filters Video ''' self.actionGray.setChecked(False) self.actionInvert_Color.setChecked(False) self.actionMono_Filter.setChecked(False) self.actionCanny_edge_detection.setChecked(False) self.actionAuto_Contrast_Filter.setChecked(False) self.actionMirroredH.setChecked(False) self.videoWidget.RestoreFilters() sender.setChecked(value) return # End Snnipet FILTERS def isMuted(self): ''' Is muted video property''' return self.playerMuted def setMuted(self): ''' Muted video ''' if self.player.isMuted(): self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_up.png")) self.player.setMuted(False) self.volumeSlider.setEnabled(True) else: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_off.png")) self.player.setMuted(True) self.volumeSlider.setEnabled(False) return def stop(self): ''' Stop video''' # Prevent Error in a Video Utils.Disable Magnifier if self.actionMagnifying_glass.isChecked(): self.actionMagnifying_glass.trigger() # Stop Video self.fakeStop() return def volume(self): ''' Volume Slider ''' return self.volumeSlider.value() def setVolume(self, volume): ''' Tooltip and set Volume value and icon ''' self.player.setVolume(volume) self.showVolumeTip(volume) if 0 < volume <= 30: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_30.png")) elif 30 < volume <= 60: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_60.png")) elif 60 < volume <= 100: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_up.png")) elif volume == 0: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_off.png")) def EndMedia(self): ''' Button end video position ''' if self.player.isVideoAvailable(): self.player.setPosition(self.player.duration()) self.videoWidget.update() return def StartMedia(self): ''' Button start video position ''' if self.player.isVideoAvailable(): self.player.setPosition(0) self.videoWidget.update() return def forwardMedia(self): ''' Button forward Video ''' forwardTime = int(self.player.position()) + 10 * 1000 if forwardTime > int(self.player.duration()): forwardTime = int(self.player.duration()) self.player.setPosition(forwardTime) def rewindMedia(self): ''' Button rewind Video ''' rewindTime = int(self.player.position()) - 10 * 1000 if rewindTime < 0: rewindTime = 0 self.player.setPosition(rewindTime) def AutoRepeat(self, checked): ''' Button AutoRepeat Video ''' if checked: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) return def showVolumeTip(self, _): ''' Volume Slider Tooltip Trick ''' self.style = self.volumeSlider.style() self.opt = QStyleOptionSlider() self.volumeSlider.initStyleOption(self.opt) rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt, self.style.SC_SliderHandle) self.tip_offset = QPoint(5, 15) pos_local = rectHandle.topLeft() + self.tip_offset pos_global = self.volumeSlider.mapToGlobal(pos_local) QToolTip.showText(pos_global, str(self.volumeSlider.value()) + " %", self) def showMoveTip(self, currentInfo): ''' Player Silder Move Tooptip Trick ''' self.style = self.sliderDuration.style() self.opt = QStyleOptionSlider() self.sliderDuration.initStyleOption(self.opt) rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt, self.style.SC_SliderHandle) self.tip_offset = QPoint(5, 15) pos_local = rectHandle.topLeft() + self.tip_offset pos_global = self.sliderDuration.mapToGlobal(pos_local) tStr = _seconds_to_time(currentInfo) QToolTip.showText(pos_global, tStr, self) def durationChanged(self, duration): ''' Duration video change signal ''' duration /= 1000 self.duration = duration self.sliderDuration.setMaximum(duration) def positionChanged(self, progress): ''' Current Video position change ''' progress /= 1000 if not self.sliderDuration.isSliderDown(): self.sliderDuration.setValue(progress) self.updateDurationInfo(progress) def updateDurationInfo(self, currentInfo): ''' Update labels duration Info and CallBack Metadata ''' duration = self.duration self.currentInfo = currentInfo if currentInfo or duration: totalTime = _seconds_to_time(duration) currentTime = _seconds_to_time(currentInfo) tStr = currentTime + " / " + totalTime currentTimeInfo = _seconds_to_time_frac(currentInfo) # Get Metadata from buffer if not self.isStreaming: self.get_metadata_from_buffer(currentTimeInfo) else: qgsu.showUserAndLogMessage("", "Streaming on ", onlyLog=True) nextTime = currentInfo + self.pass_time / 1000 nextTimeInfo = _seconds_to_time_frac(nextTime) self.callBackMetadata(currentTimeInfo, nextTimeInfo) else: tStr = "" self.labelDuration.setText(tStr) def handleCursor(self, status): ''' Change cursor ''' if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia): self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def statusChanged(self, status): ''' Signal Status video change ''' self.handleCursor(status) if status is QMediaPlayer.LoadingMedia or status is QMediaPlayer.StalledMedia or status is QMediaPlayer.InvalidMedia: self.videoAvailableChanged(False) elif status == QMediaPlayer.InvalidMedia: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", self.player.errorString()), level=QGis.Warning) self.videoAvailableChanged(False) else: self.videoAvailableChanged(True) def playFile(self, videoPath): ''' Play file from path ''' try: RemoveVideoLayers() RemoveGroupByName() # if "udp://" in videoPath: # host, port = videoPath.split("://")[1].split(":") # receiver = UDPClient(host, int(port), type="udp") # receiver.show() # self.close() # return # if "tcp://" in videoPath: # host, port = videoPath.split("://")[1].split(":") # receiver = UDPClient(host, port, type="tcp") # receiver.show() # self.close() # return self.fileName = videoPath self.playlist = QMediaPlaylist() if self.isStreaming: url = QUrl(videoPath) else: url = QUrl.fromLocalFile(videoPath) qgsu.showUserAndLogMessage("", "Added: " + str(url), onlyLog=True) self.playlist.addMedia(QMediaContent(url)) self.player.setPlaylist(self.playlist) self.setWindowTitle( QCoreApplication.translate("QgsFmvPlayer", 'Playing : ') + os.path.basename(os.path.normpath(videoPath))) CreateVideoLayers() self.clearMetadata() self.HasFileAudio = True if not self.HasAudio(videoPath): self.actionAudio.setEnabled(False) self.actionSave_Audio.setEnabled(False) self.HasFileAudio = False # Recenter map on video initial point if self.initialPt: rect = QgsRectangle(self.initialPt[1], self.initialPt[0], self.initialPt[1], self.initialPt[0]) self.iface.mapCanvas().setExtent(rect) self.iface.mapCanvas().refresh() self.playClicked(True) except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", 'Open Video File : '), str(e), level=QGis.Warning) def ReciconUpdate(self, _): ''' Record Button Icon Effect ''' self.btn_Rec.setIcon(QIcon(self.RecGIF.currentPixmap())) def StopRecordAnimation(self): '''Stop record gif animation''' self.RecGIF.frameChanged.disconnect(self.ReciconUpdate) self.RecGIF.stop() self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png")) # TODO: Make in other thread def RecordVideo(self, value): ''' Cut Video ''' currentTime = _seconds_to_time(self.currentInfo) if value is False: self.endRecord = currentTime _, file_extension = os.path.splitext(self.fileName) out, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save video record"), isSave=True, exts=file_extension[1:]) if not out: self.StopRecordAnimation() return p = _spawn([ '-i', self.fileName, '-ss', self.startRecord, '-to', self.endRecord, '-preset', 'ultrafast', '-c', 'copy', out ]) p.communicate() qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Save file succesfully!")) self.StopRecordAnimation() else: self.startRecord = currentTime self.RecGIF.frameChanged.connect(self.ReciconUpdate) self.RecGIF.start() return def videoAvailableChanged(self, available): ''' Buttons for video available ''' # self.btn_Color.setEnabled(available) self.btn_CaptureFrame.setEnabled(available) self.gb_PlayerControls.setEnabled(available) return def toggleGroup(self, state): ''' Toggle GroupBox ''' sender = self.sender() if state: sender.setFixedHeight(sender.sizeHint().height()) else: sender.setFixedHeight(15) def fakeStop(self): '''self.player.stop() make a black screen and not reproduce it again''' self.player.pause() self.StartMedia() self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png")) def playClicked(self, _): ''' Stop and Play video ''' if self.playerState in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.btn_play.setIcon(QIcon(":/imgFMV/images/pause.png")) # Uncheck Ruler self.videoWidget.ResetDrawRuler() self.actionRuler.setChecked(False) self.videoWidget.SetRuler(False) # Play Video self.player.play() elif self.playerState == QMediaPlayer.PlayingState: self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png")) self.player.pause() def seek(self, seconds): '''Slider Move''' self.player.setPosition(seconds * 1000) self.showMoveTip(seconds) def convertVideo(self): '''Convert Video To Other Format ''' out, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save Video as..."), isSave=True, exts=[ "mp4", "ogg", "avi", "mkv", "webm", "flv", "mov", "mpg", "mp3" ]) if not out: return # TODO : Make Correct format Conversion and embebed metadata info = self.converter.probeInfo(self.fileName) if info is not None: if self.HasFileAudio: audio_codec = info.audio.codec audio_samplerate = info.audio.audio_samplerate audio_channels = info.audio.audio_channels video_codec = info.video.codec video_width = info.video.video_width video_height = info.video.video_height video_fps = info.video.video_fps _, out_ext = os.path.splitext(out) if self.HasFileAudio: options = { 'format': out_ext[1:], 'audio': { 'codec': audio_codec, 'samplerate': audio_samplerate, 'channels': audio_channels }, 'video': { 'codec': video_codec, 'width': video_width, 'height': video_height, 'fps': video_fps } } else: options = { 'format': out_ext[1:], 'video': { 'codec': video_codec, 'width': video_width, 'height': video_height, 'fps': video_fps } } taskConvertVideo = QgsTask.fromFunction('Converting Video Task', self.converter.convert, infile=self.fileName, outfile=out, options=options, twopass=False, on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskConvertVideo) def CreateBitratePlot(self): ''' Create video Plot Bitrate Thread ''' sender = self.sender().objectName() if sender == "actionAudio": taskactionAudio = QgsTask.fromFunction( 'Show Audio Bitrate', self.BitratePlot.CreatePlot, fileName=self.fileName, output=None, t='audio', on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskactionAudio) elif sender == "actionVideo": taskactionVideo = QgsTask.fromFunction( 'Show Video Bitrate', self.BitratePlot.CreatePlot, fileName=self.fileName, output=None, t='video', on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskactionVideo) elif sender == "actionSave_Audio": fileaudio, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save Audio Bitrate Plot"), isSave=True, exts=[ "png", "pdf", "pgf", "eps", "ps", "raw", "rgba", "svg", "svgz" ]) if not fileaudio: return taskactionSave_Audio = QgsTask.fromFunction( 'Save Action Audio Bitrate', self.BitratePlot.CreatePlot, fileName=self.fileName, output=fileaudio, t='audio', on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskactionSave_Audio) elif sender == "actionSave_Video": filevideo, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save Video Bitrate Plot"), isSave=True, exts=[ "png", "pdf", "pgf", "eps", "ps", "raw", "rgba", "svg", "svgz" ]) if not filevideo: return taskactionSave_Video = QgsTask.fromFunction( 'Save Action Video Bitrate', self.BitratePlot.CreatePlot, fileName=self.fileName, output=filevideo, t='video', on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskactionSave_Video) def finishedTask(self, e, result=None): """ Common finish task function """ if e is None: if result is None: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", 'Completed with no exception and no result '\ '(probably manually canceled by the user)'), level=QGis.Warning) else: if "Georeferencing" in result['task']: return qgsu.showUserAndLogMessage( QCoreApplication.translate( "QgsFmvPlayer", "Succesfully " + result['task'] + "!")) if "Bitrate" in result['task']: self.matplot = ShowPlot(self.BitratePlot.bitrate_data, self.BitratePlot.frame_count, self.fileName, self.BitratePlot.output) if result['task'] == 'Show Video Info Task': self.showVideoInfoDialog(self.converter.bytes_value) else: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "Failed " + result['task'] + "!"), level=QGis.Warning) raise e def ExtractAllFrames(self): """ Extract All Video Frames Task """ directory = askForFolder( self, QCoreApplication.translate("QgsFmvPlayer", "Save all Frames"), options=QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly) if directory: taskExtractAllFrames = QgsTask.fromFunction( 'Save All Frames Task', self.SaveAllFrames, fileName=self.fileName, directory=directory, on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskExtractAllFrames) return def SaveAllFrames(self, task, fileName, directory): vidcap = cv2.VideoCapture(fileName) length = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT)) count = 0 while not task.isCanceled(): _, image = vidcap.read() cv2.imwrite(directory + "\\frame_%d.jpg" % count, image) # save frame as JPEG file task.setProgress(count * 100 / length) count += 1 vidcap.release() cv2.destroyAllWindows() if task.isCanceled(): return None return {'task': task.description()} def ExtractCurrentFrame(self): """ Extract Current Frame Task """ image = self.videoWidget.GetCurrentFrame() output, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save Current Frame"), isSave=True, exts=["png", "jpg", "bmp", "tiff"]) if not output: return taskCurrentFrame = QgsTask.fromFunction('Save Current Frame Task', self.SaveCapture, image=image, output=output, on_finished=self.finishedTask, flags=QgsTask.CanCancel) QgsApplication.taskManager().addTask(taskCurrentFrame) return def SaveCapture(self, task, image, output): ''' Save Current Frame ''' image.save(output) if task.isCanceled(): return None return {'task': task.description()} def OpenQgsFmvMetadata(self): """ Open Metadata Dock """ if self.metadataDlg is None: self.metadataDlg = QgsFmvMetadata(parent=self, player=self) self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg) self.metadataDlg.show() else: self.metadataDlg.show() return def showVideoInfoDialog(self, outjson): """ Show Video Information Dialog """ view = QTreeView() model = QJsonModel() view.setModel(model) model.loadJsonFromConsole(outjson) self.VideoInfoDialog = QDialog(self) self.VideoInfoDialog.setWindowTitle( QCoreApplication.translate("QgsFmvPlayer", "Video Information : ") + self.fileName) self.VideoInfoDialog.setWindowIcon( QIcon(":/imgFMV/images/video-info.png")) self.verticalLayout = QVBoxLayout(self.VideoInfoDialog) self.verticalLayout.addWidget(view) view.expandAll() view.header().setSectionResizeMode(QHeaderView.ResizeToContents) self.VideoInfoDialog.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint) self.VideoInfoDialog.setObjectName("VideoInfoDialog") self.VideoInfoDialog.resize(500, 400) self.VideoInfoDialog.show() def closeEvent(self, _): """ Close Event """ self.stop() self.parent._PlayerDlg = None self.parent.ToggleActiveFromTitle() RemoveVideoLayers() RemoveGroupByName() ResetData() try: self.metadataDlg.hide() except Exception: None try: self.matplot.close() except Exception: None # Restore Filters State self.videoWidget.RestoreFilters()
class MainWindow(QMainWindow, Ui_GrilHappyQMW): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setupUi(self) self.setWindowTitle('Grils HappyToo!!!') self.setVisible(0) self.preloadDialog = QDialog() self.screen = QDesktopWidget().screenGeometry() """ gif开场动画 """ self.movie=QMovie(":/girl/img/showheart.gif") self.movie.updated.connect(self.gifFinished) self.movie.destroyed.connect(self.showMainWindow) self.movie.setSpeed(1111) """ 开场dialog """ self.preloadDialog.setWindowFlag(Qt.FramelessWindowHint) self.preloadDialog.setMask(QRegion(12,12,190,190)) self.preloadDialog.move(( self.screen.width()-200) / 2, ( self.screen.height()-200) / 2) gifLayout=QHBoxLayout() gifLabel=QLabel() gifLabel.setMovie(self.movie) gifLayout.addWidget(gifLabel) self.preloadDialog.setLayout(gifLayout) self.preloadDialog.setVisible(1) self.movie.start() def showMainWindow(self): self.move((self.screen.width() - self.width()) / 2, (self.screen.height() - self.height()) / 2) self.meidaPlayer=QMediaPlayer() self.playlist=QMediaPlaylist() self.playlist.setCurrentIndex(1); self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile("video/Radio-Digital-Scheme-Live-Wallpaper~1.mp4"))) self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.meidaPlayer.setPlaylist(self.playlist) videoWidget = QVideoWidget() videoWidget.setAspectRatioMode(Qt.IgnoreAspectRatio) videoWidget.setAutoFillBackground(True) videoWidget.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)) # videoWidget.setMinimumSize(videoWidget.size()) self.meidaPlayer.setVideoOutput(videoWidget) self.verticalLayout_2.insertWidget(0,videoWidget) self.meidaPlayer.play() self.setVisible(1) def codeRain(self): label=QLabel(parent=self) s=''.join([word+'\n' for word in list("我们的每一天,都无法重来,将管理学书籍读遍依旧管不了因你悸动的心。")]) label.setText(s) label.raise_() label.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)) label.setMaximumWidth(12) label.setMaximumHeight(len(s)*10) label.setMinimumHeight(len(s)*10) label.setWordWrap(True) label.setAlignment(Qt.AlignTop) label.setStyleSheet(""" font: 87 10pt "Arial"; color: rgb(0, 49, 79); """) label.setAttribute(Qt.WA_TranslucentBackground) label.show() ani=QPropertyAnimation(label, b'pos', self) ani.setDuration(10000) xr=random.randint(0,self.label.width()) yr=random.randint(0,self.height()) ani.setStartValue(QPoint(xr,-self.width())) ani.setEndValue(QPoint(xr,self.height())) ani.finished.connect(label.deleteLater) ani.start() def gifFinished(self): if(self.movie.currentFrameNumber()==self.movie.frameCount()-1): self.preloadDialog.close() self.movie.stop() self.showPreload() def showPreload(self): self.preloadDialog = QDialog() self.preloadImage=QPixmap(':/girl/img/preload.png') size = self.preloadImage.size() self.move(( self.screen.width() - size.width()) / 2, ( self.screen.height() - size.height()) / 2) self.preloadDialog.setMinimumSize(size) layout=QHBoxLayout() label=QLabel() label.setPixmap(self.preloadImage) layout.addWidget(label) self.preloadDialog.setLayout(layout) self.preloadDialog.setMask(QRegion(QRect(self.preloadImage.rect().x()+15,self.preloadImage.rect().y()+15,self.preloadImage.rect().width()-20,self.preloadImage.rect().height()-35))) self.timer = QTimer() self.preloadDialog.show() self.timer.timeout.connect(self.faded) self.timer.start(3000) self.timer.setInterval(10) self.opacity = 100 def faded(self): self.preloadDialog.setWindowOpacity(self.opacity / 100) if self.opacity <= 0: self.preloadDialog.close() """ 开启代码雨 """ self.showMainWindow() self.codeTimer=QTimer() self.codeTimer.timeout.connect(self.codeRain) self.codeTimer.start(1000) self.codeTimer.setInterval(5000) self.timer.stop() else: self.opacity -= 13 def closeEvent(self, a0) -> None: self.codeTimer.stop() for i in range(100,0,-1): self.setWindowOpacity(i/100) time.sleep(0.002)
class Reproductor(Genesis, QMainWindow): """ Instalar MatroskaSplitter y LAVFilters(Codecs), para que pueda reproducir videos y audio LAVFilters https://github.com/Nevcairiel/LAVFilters/releases MatroskaSplitter https://haali.su/mkv/ """ def __init__(self, *args, **kwargs): super(Reproductor, self).__init__() self.transcurso = 0 # Centramos la ventana principal self.centrar() # Inicializamos el modulo QMediaPlayer self.media = QMediaPlayer() self.media.setVolume(5) self.reproducir.setEnabled(False) # Setup the playlist. self.lista_repro = QMediaPlaylist() self.media.setPlaylist(self.lista_repro) self.modelo = ListaModelo(self.lista_repro) self.lista.setModel(self.modelo) self.lista_repro.currentIndexChanged.connect(self.cambio_lista_repro) modelo_seleccion = self.lista.selectionModel() modelo_seleccion.selectionChanged.connect(self.seleccion_lista_repro) # ********** Inicializamos el modulo QVideoWidget ******* self.video = QVideoWidget() # Agregamos el modulo QVideoWidget al grid donde se mostrara el video self.reproductor.addWidget(self.video) # Tambien lo agregamos al modulo QMediaPlayer self.media.setVideoOutput(self.video) # Conectamos el boton de reproducir con su metodo correspondiente self.reproducir.clicked.connect(self.play_video) # Conectamos el Skider del tiempo con su metodo correspondiente self.tiempo.sliderMoved.connect(self.posicion_establecida) # ****** Conectamos los estados del modulo QMediaPlayer con sus correspondientes metodos ***** self.media.stateChanged.connect(self.cambios_video) self.media.positionChanged.connect(self.posicion_video) self.media.durationChanged.connect(self.duracion_video) self.total_duracion = 0 self.cargar.clicked.connect(self.abrir_archivo) #self.marco.origen.connect(self.arrastrar_soltar) self.parar.pressed.connect(self.media.stop) self.atras.pressed.connect(self.lista_repro.previous) self.adelante.pressed.connect(self.lista_repro.next) self.volumen.valueChanged.connect(self.media.setVolume) self.logo_volumen.clicked.connect(self.silenciar) self.lista.doubleClicked.connect(self.play_video) self.video.keyPressEvent = self.keyPressEvent # ****** Boton de menu ****** self.lista.setMinimumSize(QSize(0, 0)) self.lista_visible = True self.menu.clicked.connect(self.boton_menu) self.setAcceptDrops(True) self.primera_reproduccion = True self.show() # ---------------- Inicio de Metodos --------------------------- # # Detectamos una tecla presionada def keyPressEvent(self, event): if event.key() == Qt.Key_F11 or event.key() == Qt.Key_Escape and self.video.isFullScreen(): self.fullscreen_change() elif event.key() == Qt.Key_Space: self.play_video() #Pantalla completa def fullscreen_change(self): if self.video.isFullScreen(): self.video.setFullScreen(False) self.lista.setMinimumSize(QSize(300, 16777215)) else: self.video.setFullScreen(True) # Ocultar y mostrar la lista de reproduccion def boton_menu(self): if self.lista_visible: self.lista.setVisible(False) size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.marco.setSizePolicy(size_policy) self.lista_visible = False else: self.lista.setVisible(True) self.lista_visible = True # Metodos para arrastrar y soltar en la lista de reproduccion def dragEnterEvent(self, e): if e.mimeData().hasUrls(): e.acceptProposedAction() # Metodos para arrastrar y soltar en la lista de reproduccion def dropEvent(self, e): for url in e.mimeData().urls(): self.lista_repro.addMedia(QMediaContent(url)) self.lista_repro.setPlaybackMode(QMediaPlaylist.Loop) self.media.setPlaylist(self.lista_repro) self.reproducir.setEnabled(True) self.reproductor.removeWidget(self.logo) self.media.play() self.modelo.layoutChanged.emit() """ # If not playing, seeking to first of newly added + play. if self.media.state() != QMediaPlayer.PlayingState: #i = self.lista_repro.mediaCount() - len(e.mimeData().urls()) #print(i) #self.lista_repro.setCurrentIndex(i) self.reproducir.setEnabled(True) self.reproductor.removeWidget(self.logo) #self.media.setPlaylist(playlist) self.media.play() """ # Metodo para cargar el video en cuestion def abrir_archivo(self): archivo, _ = QFileDialog.getOpenFileName(self, ' Abrir Archivo !!!', 'C:/Users/Duque/Videos', 'Solo Video (*.mp4 *.mov *.flv *.mkv *.ts *.mts *.avi);; Solo Audio (*.mp3 *.flac *.m4a *.wav)') if archivo != '': self.reproductor.removeWidget(self.logo) self.primera_reproduccion = False self.lista_repro.addMedia(QMediaContent(QUrl.fromLocalFile(archivo))) self.reproducir.setEnabled(True) self.modelo.layoutChanged.emit() # Metodo para el cambio en la lista de reproduccion def cambio_lista_repro(self, i): if i > -1: ix = self.modelo.index(i) self.lista.setCurrentIndex(ix) # Metodo para la seleccion en la lista de reproduccion def seleccion_lista_repro(self, ix): i = ix.indexes()[0].row() self.lista_repro.setCurrentIndex(i) # Metodo para silenciar el audio o video def silenciar(self): if self.media.isMuted(): self.media.setMuted(False) icon = QIcon() icon.addPixmap(QPixmap(":/img/altavoz3.png"), QIcon.Normal, QIcon.Off) self.logo_volumen.setIcon(icon) self.logo_volumen.setToolTip(' Silenciar ') else: self.media.setMuted(True) icon = QIcon() icon.addPixmap(QPixmap(":/img/altavoz4.png"), QIcon.Normal, QIcon.Off) self.logo_volumen.setIcon(icon) self.logo_volumen.setToolTip(' Restablecer Sonido ') @pyqtSlot(str) def arrastrar_soltar(self, archivo): if archivo != '': self.media.setMedia(QMediaContent(QUrl.fromLocalFile(archivo))) self.reproducir.setEnabled(True) self.lista_repro.addMedia(QMediaContent(QUrl.fromLocalFile(archivo))) self.modelo.layoutChanged.emit() # Metodo para reproducir el video en cuestion def play_video(self): if self.primera_reproduccion: self.reproductor.removeWidget(self.logo) self.primera_reproduccion = False if self.media.state() == QMediaPlayer.PlayingState: self.media.pause() else: self.media.play() # Metodo que detecta el estado de cambio del boton reproducir de play a pausa y viceversa def cambios_video(self, state): if self.media.state() == QMediaPlayer.PlayingState: icon = QIcon() icon.addPixmap(QPixmap(":/img/pausa.png"), QIcon.Normal, QIcon.Off) self.reproducir.setIcon(icon) self.reproducir.setToolTip(' Pausar Video o Audio ') QToolTip.setFont(QFont('Cascadia Code PL', 18)) else: icon = QIcon() icon.addPixmap(QPixmap(":/img/play.svg"), QIcon.Normal, QIcon.Off) self.reproducir.setIcon(icon) self.reproducir.setToolTip(' Reproducir Video o Audio ') QToolTip.setFont(QFont('Cascadia Code PL', 18)) def duracion_video(self, duracion): """ # Detecta la duración del vídeo en el slider. """ self.tiempo.setMaximum(duracion) self.total_duracion = duracion # Metodo que detecta la posiscion del video en el slider def posicion_video(self, posicion): if posicion >= 0: reproduccion = f'{detalle_tiempo(posicion)} || {detalle_tiempo(self.total_duracion)}' self.datos.setText(reproduccion) self.tiempo.blockSignals(True) self.tiempo.setValue(posicion) self.tiempo.blockSignals(False) # Metodo que detecta la posiscion establecida del modulo QMediaPlayer def posicion_establecida(self, position): self.media.setPosition(position) def errores(self): self.reproducir.setEnabled(False) # self.lbl.setText("Error: " + self.media.errorString()) # Metodo para centrar la ventana principal def centrar(self): ventana = self.frameGeometry() centro = QDesktopWidget().availableGeometry().center() # print(centro) ventana.moveCenter(centro) self.move(ventana.topLeft())
class Player(Qt.QWidget): """docstring for Player""" fullScreenChanged = Qt.pyqtSignal(bool) def __init__(self, playlist, parent=None): # create player super(Player, self).__init__(parent) self.trackInfo = '' self.statusInfo = '' self.duration = 0 # create player object self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.name = 'Current playlist' self.player.setPlaylist(self.playlist) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.metaDataChanged.connect(self.metaDataChanged) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.bufferStatusChanged.connect(self.bufferingProgress) # self.player.videoAvailableChanged.connect(self.videoAvailableChanged) self.player.error.connect(self.displayErrorMessage) # connect with VideoWidget # self.videoWidget = VideoWidget() # self.player.setVideoOutput(self.videoWidget) # connect with PlaylistModel self.playlistModel = PlaylistModel() self.playlistModel.setPlaylist(self.playlist) self.playlistView = Qt.QListView() self.playlistView.setModel(self.playlistModel) self.playlistView.setCurrentIndex(self.playlistModel.index( self.playlist.currentIndex(), 0)) # change to next song self.playlistView.activated.connect(self.jump) self.slider = Qt.QSlider(QtCore.Qt.Horizontal) self.slider.setRange(0, self.player.duration() / 1000) self.labelDuration = Qt.QLabel() self.slider.sliderMoved.connect(self.seek) # create histogram self.labelHistogram = Qt.QLabel() self.labelHistogram.setText('Histogram: ') self.histogram = HistogramWidget() histogramLayout = Qt.QHBoxLayout() histogramLayout.addWidget(self.labelHistogram) histogramLayout.addWidget(self.histogram, 1) # create videoProbe self.videoProbe = Qt.QVideoProbe() self.videoProbe.videoFrameProbed.connect(self.histogram.processFrame) self.videoProbe.setSource(self.player) # add control controls = Controllers() controls.setState(self.player.state()) controls.setVolume(self.player.volume()) controls.setMuted(controls.isMuted()) # connect player's controls with Controllers controls.play.connect(self.player.play) controls.pause.connect(self.player.pause) controls.stop.connect(self.player.stop) controls.next.connect(self.playlist.next) controls.previous.connect(self.previousAction) controls.changeVolume.connect(self.player.setVolume) controls.changeMuting.connect(self.player.setMuted) # setPlaybackRate is from QMediaPlayer controls.changeSpeed.connect(self.player.setPlaybackRate) # controls.stop.connect(self.videoWidget.update) self.player.stateChanged.connect(controls.setState) self.player.volumeChanged.connect(controls.setVolume) self.player.mutedChanged.connect(controls.setMuted) # create fullScreenButton # self.fullScreenButton = Qt.QPushButton('FullScreen') # self.fullScreenButton.setCheckable(True) # displayLayout displayLayout = Qt.QHBoxLayout() # displayLayout.addWidget(self.videoWidget, 2) displayLayout.addWidget(self.playlistView) # controlLayout controlLayout = Qt.QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) # connect controlLayout with controls controlLayout.addWidget(controls) controlLayout.addStretch(1) # connect controlLayout with fullScreenButton # controlLayout.addWidget(self.fullScreenButton) # visualize player layout = Qt.QVBoxLayout() layout.addLayout(displayLayout) # layout for sliding song playing hLayout = Qt.QHBoxLayout() hLayout.addWidget(self.slider) hLayout.addWidget(self.labelDuration) layout.addLayout(hLayout) layout.addLayout(controlLayout) layout.addLayout(histogramLayout) # set icon self.setWindowIcon(Qt.QIcon('favicon.ico')) # create menus toolBar = Qt.QToolBar() # create basic actions self.createActions() # create simple button to repeat song self.repeatButton = Qt.QToolButton() self.repeatButton.setDefaultAction(self.repeatAct) # create playOnceButton self.playOnceButton = Qt.QToolButton() self.playOnceButton.setDefaultAction(self.playOnceAct) self.playOnceButton.setEnabled(False) # create shuffleButton self.shuffleButton = Qt.QToolButton() self.shuffleButton.setDefaultAction(self.shuffleAct) # create sequentialButton self.sequentialButton = Qt.QToolButton() self.sequentialButton.setDefaultAction(self.sequentialAct) # create fileButton for fileMenu fileButton = Qt.QToolButton() fileButton.setText('File') fileButton.setPopupMode(Qt.QToolButton.MenuButtonPopup) fileButton.setMenu(self.popFileMenu()) # create editButton for editMenu closeButton = Qt.QToolButton() closeButton.setText('Edit') closeButton.setDefaultAction(self.fileCloseAct) # display in toolBar these buttons toolBar.addWidget(self.repeatButton) toolBar.addWidget(self.playOnceButton) toolBar.addWidget(self.shuffleButton) toolBar.addWidget(self.sequentialButton) toolBar.addWidget(fileButton) toolBar.addWidget(closeButton) # add toolBar to layout of the player layout.addWidget(toolBar) layout.addWidget(Qt.QGroupBox()) self.setWindowTitle("Python Music Player") self.setLayout(layout) if not self.player.isAvailable(): Qt.QMessageBox(self, 'Unavailable service') # self.displayErrorMessage() controls.setEnabled(False) self.playlistView.setEnabled(False) self.fullScreenButton.setEnabled(False) self.metaDataChanged() self.addToPlaylist(playlist) # create fileMenu def popFileMenu(self): aMenu = Qt.QMenu(self) aMenu.addAction(self.fileOpenAct) aMenu.addAction(self.fileCloseAct) return aMenu def createActions(self): self.repeatAct = Qt.QAction('Repeat', self, triggered=self.repeatSong) self.playOnceAct = Qt.QAction( 'Play once', self, triggered=self.playOnceSong) self.shuffleAct = Qt.QAction( 'Shuffle', self, triggered=self.playlist.shuffle) self.sequentialAct = Qt.QAction( 'Sequential', self, triggered=self.playSequential) self.fileOpenAct = Qt.QAction('Open', self, triggered=self.open) self.fileOpenAct.setShortcut('Ctrl+O') self.fileCloseAct = Qt.QAction('Close', self, triggered=self.close) self.fileCloseAct.setShortcut('Ctrl+Q') def repeatSong(self): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.repeatButton.setEnabled(False) self.playOnceButton.setEnabled(True) def playOnceSong(self): self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.playOnceButton.setEnabled(False) self.repeatButton.setEnabled(True) # unproperly used def playSequential(self): self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) # get and display song duration def durationChanged(self, duration): duration /= 1000 self.duration = duration self.slider.setMaximum(duration) # change slider position def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.updateDurationInfo(progress) def updateDurationInfo(self, currentInfo): duration = self.duration if currentInfo or duration: currentTime = QtCore.QTime( (currentInfo / 3600) % 60, # hours (currentInfo / 60) % 60, # minutes currentInfo % 60, # seconds (currentInfo * 1000) % 1000) # miliseconds totalTime = QtCore.QTime( (duration / 3600) % 60, # hours (duration / 60) % 60, # minutes duration % 60, # seconds (duration * 1000) % 1000) # miliseconds formating = 'hh:mm:ss' if duration > 3600 else 'mm:ss' toString = (currentTime.toString(formating) + ' / ' + totalTime.toString(formating)) else: toString = '' self.labelDuration.setText(toString) def metaDataChanged(self): if self.player.isMetaDataAvailable(): self.setTrackInfo('{0} - {1}'.format( self.player.metaData(Qt.QMediaMetaData.AlbumArtist), self.player.metaData(Qt.QMediaMetaData.Title))) def setTrackInfo(self, info): self.trackInfo = info if self.statusInfo: self.setWindowTitle('{0} | {1}'.format( self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def playlistPositionChanged(self, position): self.playlistView.setCurrentIndex( self.playlistModel.index(position, 0)) def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo('Loading...') elif status == QMediaPlayer.StalledMedia: self.setStatusInfo('Media Stalled') elif status == QMediaPlayer.EndOfMedia: Qt.QApplication.alert(self) elif status == QMediaPlayer.InvalidMedia: self.displayErrorMessage() else: self.setStatusInfo('') def handleCursor(self, status): if status in [QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia]: self.setCursor(QtCore.Qt.BusyCursor) else: self.unsetCursor() def setStatusInfo(self, info): self.statusInfo = info if self.statusInfo: self.setWindowTitle('{0} | {1}'.format( self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def bufferingProgress(self, progress): self.setStatusInfo('Buffering {0}'.format(progress)) def displayErrorMessage(self): self.statusInfo(self.player.errorString()) def jump(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def seek(self, seconds): self.player.setPosition(seconds * 1000) def previousAction(self): self.playlist.previous() def close(self): choice = Qt.QMessageBox.question( self, 'Close', 'Close the app?', Qt.QMessageBox.Yes | Qt.QMessageBox.No) if choice == Qt.QMessageBox.Yes: sys.exit() def open(self): names, _ = Qt.QFileDialog.getOpenFileNames(self, 'Open Files') # ['/home/milka/Documents/MusicPlayer/song.mp3'] self.addToPlaylist(names) def addToPlaylist(self, names): for name in names: fileInfo = Qt.QFileInfo(name) if fileInfo.exists(): url = QtCore.QUrl.fromLocalFile(fileInfo.absoluteFilePath()) # save_to_db song url create_song( url.path(), self.duration, playlist_name=self.name) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(Qt.QMediaContent(url)) else: url = QtCore.QUrl(name) if url.isValid(): self.playlist.addMedia(Qt.QMediaContent(url))
class MainWindow(QMainWindow): def __init__(self, app): super(MainWindow, self).__init__() self.app = app print('window created') self.setWindowIcon(QIcon('img/icon.png')) self.setWindowTitle('Kasino') self.setPalette(QPalette(Qt.darkGreen)) self.setup_music() self.statusbar = QStatusBar(self) self.statusbar.setStyleSheet('background: white') self.setStatusBar(self.statusbar) self.statusbar.showMessage('Welcome to the Cassino game!') self.menubar = QMenuBar(self) self.optionsMenu = self.menubar.addMenu('Options') self.music_toggle = QAction() self.music_toggle.setText('Music') self.music_toggle.setShortcut('Ctrl+m') self.music_toggle.setCheckable(True) self.music_toggle.setChecked(True) self.optionsMenu.addAction(self.music_toggle) self.music_toggle.triggered.connect(self.toggle_music) self.speedGroup = QActionGroup(self) self.speedGroup.triggered.connect(self.set_speed) self.slow_speed = QAction('Slow', self.speedGroup) self.slow_speed.setCheckable(True) self.normal_speed = QAction('Normal', self.speedGroup) self.normal_speed.setCheckable(True) self.fast_speed = QAction('Fast', self.speedGroup) self.fast_speed.setCheckable(True) self.vfast_speed = QAction('Very Fast', self.speedGroup) self.vfast_speed.setCheckable(True) self.normal_speed.setChecked(True) self.speed_menu = self.optionsMenu.addMenu('Speed') self.speed_menu.addActions(self.speedGroup.actions()) self.menubar.setMouseTracking(False) self.setMenuBar(self.menubar) self.play_widget = PlayWidget(self) self.main_menu = MainMenu(self) self.start_menu = StartMenu(self) self.widgets = QStackedWidget(self) self.widgets.addWidget(self.play_widget) self.widgets.addWidget(self.main_menu) self.widgets.addWidget(self.start_menu) self.widgets.setCurrentWidget(self.main_menu) self.setCentralWidget(self.widgets) self.setGeometry(25, 50, 1028, 720) self.main_menu.startbutton.clicked.connect(self.init_game) self.main_menu.loadbutton.clicked.connect(self.load_game) self.main_menu.quitbutton.clicked.connect(self.quit) self.play_widget.quit_button.clicked.connect(self.quit_to_menu) self.play_widget.save_button.clicked.connect(self.save_game) self.start_menu.startbutton.clicked.connect(self.start_game) def setup_music(self): self.music = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) file_name = "sound/bg.mp3" self.media = QMediaContent(QUrl.fromLocalFile(file_name)) self.playlist.addMedia(self.media) self.music.setPlaylist(self.playlist) self.music.setVolume(20) self.music.play() def toggle_music(self): if self.music.isMuted(): self.music.setMuted(False) self.statusbar.showMessage('Music on', 5000) else: self.music.setMuted(True) self.statusbar.showMessage('Music off', 5000) def set_speed(self, action): if action == self.slow_speed: self.play_widget.speed = 1 elif action == self.normal_speed: self.play_widget.speed = 3 elif action == self.fast_speed: self.play_widget.speed = 4 else: self.play_widget.speed = 6 def start_game(self): self.play_widget.init_game( self.start_menu.extract_info_and_init_game()) self.widgets.setCurrentWidget(self.play_widget) self.statusbar.showMessage('Game launched', 2000) def load_game(self): path = QFileDialog.getOpenFileName(self, 'Open save file', QDir.currentPath() + '/sav')[0] if path != '': game, msg, count = load(path) self.play_widget.resume_from_save(game, msg, count) self.widgets.setCurrentWidget(self.play_widget) self.statusbar.showMessage('Loaded save file', 5000) def save_game(self): path = QFileDialog.getSaveFileName(self, 'Create save file', QDir.currentPath() + '/sav')[0] if path != '': save(path, self.play_widget.game, self.play_widget.export_log(), self.play_widget.move_count) self.statusbar.showMessage('Game saved', 5000) def init_game(self): self.widgets.setCurrentWidget(self.start_menu) self.statusbar.showMessage('Starting new game') def quit_to_menu(self): #Reset playwidget self.widgets.removeWidget(self.play_widget) speed = self.play_widget.speed self.play_widget.setParent(None) self.play_widget = PlayWidget(self) self.play_widget.speed = speed self.widgets.addWidget(self.play_widget) self.play_widget.quit_button.clicked.connect(self.quit_to_menu) self.play_widget.save_button.clicked.connect(self.save_game) self.widgets.setCurrentWidget(self.main_menu) def closeEvent(self, *args, **kwargs): #for handling closing from 'x' button self.quit() def quit(self): print('Exited game. Thanks for playing!\n') self.app.exit()
class MyWidget(QMainWindow): def __init__(self): super().__init__() # !Костыль # Запрещаю менять размер окна, т.к. не хочу работать с layout`ами self.setFixedSize(656, 532) self.setWindowIcon(QIcon('icons/icon.ico')) # Добавляем эквалайзер громкости self.equalizer = QVolumeEq((255, 255, 102), (255, 26, 10), bg_color=(0, 0, 0, 20)) self.equalizer.setParent(self) self.equalizer.move(20, 391) self.equalizer.resize(341, 31) uic.loadUi('icons/djap.ui', self) self.lightThemeAction.triggered.connect(self.change_theme) self.darkThemeAction.triggered.connect(self.change_theme) # Создаём организатор плейлистов self.playlist_handler = QPlaylistHandler() self.playlist_handler.setParent(self) self.playlist_handler.move(380, 40) # Настраиваем меню self.saveOption.triggered.connect(self.playlist_handler.save_playlist) self.saveAsOption.triggered.connect(self.playlist_handler.save_playlist_as) self.deleteOption.triggered.connect(self.playlist_handler.delete_playlist) self.aboutOption.triggered.connect(self.about) self.helpOption.triggered.connect(self.help) self.repeatModeOption.triggered.connect(self.playlist_handler.change_playmode) self.oneModeOption.triggered.connect(self.playlist_handler.change_playmode) self.randomModeOption.triggered.connect(self.playlist_handler.change_playmode) # Реализация проигрывателя и основного плейлиста self.player = QMediaPlayer() self.player.durationChanged.connect(self.update_song) self.player.setVolume(25) self.player.positionChanged.connect(self.update_timeline_position) self.queue = QMediaPlaylist(self.player) self.player.setPlaylist(self.queue) self.queue.setPlaybackMode(QMediaPlaylist.Loop) self.is_looped_queue = True # Загрузка музыки из плейлиста self.load_songs_from_playlist() # Подключаем кнопки к их функциям self.is_playing = False self.playBtn.clicked.connect(self.play_or_pause) self.queue.currentMediaChanged.connect(self.check_to_stop) self.nextBtn.clicked.connect(self.next_audio) self.prevBtn.clicked.connect(self.prev_audio) self.is_looped_current_track = False self.loopBtn.clicked.connect(self.loop_or_unloop_current_track) # Настройка слайдера звука self.volumeSlider.hide() self.volumeSlider.setValue(25) self.equalizer.setValue(25) self.volumeSlider.sliderReleased.connect(self.volumeSlider.hide) self.volumeSlider.valueChanged.connect(self.change_volume) self.volumeBtn.clicked.connect(self.change_volume) # Настройка таймлайна self.is_timeline_dragged = False self.timeline.sliderReleased.connect(self.timeline_changed) self.timeline.sliderPressed.connect(self.timeline_is_dragged) # !Костыль # Имитируем запуск аудиодорожки, чтобы подгрузить данные self.play_or_pause() self.play_or_pause() self.icon_changed() def palette(self): """Функция для создания темы""" con = sqlite3.connect('user_data.sqlite') cur = con.cursor() if int(cur.execute('SELECT * FROM theme').fetchone()[0]): palette = QPalette() palette.setColor(QPalette.Window, QColor(240, 240, 240)) palette.setColor(QPalette.WindowText, Qt.black) palette.setColor(QPalette.Base, Qt.white) palette.setColor(QPalette.AlternateBase, QColor(246, 246, 246)) palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 240)) palette.setColor(QPalette.ToolTipText, Qt.black) palette.setColor(QPalette.Text, Qt.black) palette.setColor(QPalette.Button, QColor(240, 240, 240)) palette.setColor(QPalette.ButtonText, Qt.black) palette.setColor(QPalette.BrightText, Qt.white) palette.setColor(QPalette.Highlight, QColor(0, 120, 215).lighter()) palette.setColor(QPalette.HighlightedText, Qt.white) else: palette = QPalette() palette.setColor(QPalette.Window, QColor(53, 53, 53)) palette.setColor(QPalette.WindowText, Qt.white) palette.setColor(QPalette.Base, QColor(15, 15, 15)) palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) palette.setColor(QPalette.ToolTipBase, Qt.white) palette.setColor(QPalette.ToolTipText, Qt.white) palette.setColor(QPalette.Text, Qt.white) palette.setColor(QPalette.Button, QColor(53, 53, 53)) palette.setColor(QPalette.ButtonText, Qt.white) palette.setColor(QPalette.BrightText, Qt.red) palette.setColor(QPalette.Highlight, QColor(142, 45, 197).lighter()) palette.setColor(QPalette.HighlightedText, Qt.black) return palette def change_theme(self): """Функция для смены темы""" con = sqlite3.connect('user_data.sqlite') cur = con.cursor() if self.sender() == self.lightThemeAction: cur.execute('UPDATE theme SET isit = 1') else: cur.execute('UPDATE theme SET isit = 0') con.commit() QMessageBox.warning(self, 'DJust Audio Player', 'Чтобы изменения вступили в силу, ' 'перезапустите приложение.', QMessageBox.Ok) def help(self): """Функция для показа формы справки""" self.help = QHelp() def about(self): """Функция для показа формы О программе""" self.about = QAbout() def delete_song_from_mediaplayer(self, index): """Удалить трек из медиаплеера""" self.queue.removeMedia(index) def add_song_to_mediaplayer(self, url): """Добавить трек в медиаплеер""" self.queue.addMedia(QMediaContent(QUrl(url))) def change_track_by_click(self, row): """Функция для смены трека по нажатию в списке""" self.queue.setCurrentIndex(row) def check_to_stop(self): """Проверяем, чтобы плеер не играл с пустым плейлистом""" if self.queue.isEmpty() and self.is_playing: self.play_or_pause() def load_songs_from_playlist(self): """Загрузка музыки из БД в плейлист""" self.queue.clear() for url in self.playlist_handler.urls(): self.queue.addMedia(QMediaContent(QUrl(url))) def icon_changed(self): """Функция для вывода обложки трека""" def noicon(): """В случае отсутствия обложки эта функция ставить свою заглушку""" try: pixmap = QPixmap() if pixmap.load('icons/noicon.png'): self.audioPic.setPixmap(pixmap) except Exception as e: print(e.__class__.__name__, ': ', e, sep='') try: # Читаем метаданные трека n = self.queue.currentIndex() url = self.playlist_handler.urls()[n if n > -1 else 0] file = File(url) for i in file.tags.keys(): if 'APIC:' in i: artwork = file.tags[i].data break else: raise KeyError # Переводим их в байтовый массив ba = QByteArray(artwork) # И загружаем на форму, если это возможно pixmap = QPixmap() if pixmap.loadFromData(ba): self.audioPic.setPixmap(pixmap.scaled(341, 341, Qt.IgnoreAspectRatio)) else: raise KeyError except Exception as e: # print(e.__class__.__name__, ': ', e, sep='') noicon() def timeline_is_dragged(self): """Мини-функция для изменения переменной""" # При вызове этой функции мы понимаем, что пользователь # взаимодействует с таймлайном трека self.is_timeline_dragged = True def timeline_changed(self): """Функция для пользовательской перемотки данного трека""" # Перематываем позицию плеера self.player.setPosition(self.timeline.value() * 1000) # Пользователь отпустил язычок слайдера и больше не взаимодействует с таймлайном self.is_timeline_dragged = False # Вызываем обновление временной шкалы, т.к. произошла перемотка self.update_timeline_position() def update_song(self): """Изменение данных о треке""" # !Костыль # Проматываем несколько миллисекунд, чтобы избежать повреждённых треков self.player.setPosition(10) # Меняем обложку self.icon_changed() # Выделяем в списке новый трек self.playlist_handler.set_current_select(self.queue.currentIndex()) # Меняем название окна в соответствии с играющим треком title = self.queue.currentMedia().canonicalUrl().path().split('/')[-1] if title: self.setWindowTitle('DJust Audio Player | %s' % title) else: self.setWindowTitle('DJust Audio Player') # Изменяем длину таймлайна на длину трека self.timeline.setMaximum(self.player.duration() // 1000) # Выводим длину трека в минутах/секундах на экран minutes, seconds = self.player.duration() // 1000 // 60, self.player.duration() // 1000 % 60 self.endTimeLabel.setText(str(minutes) + ':{:02d}'.format(seconds)) def update_timeline_position(self): """Функция для обновления временной шкалы""" # Выводим текущее положение плеера в минутах/секундах minutes, seconds = self.player.position() // 1000 // 60, self.player.position() // 1000 % 60 self.currentTimeLabel.setText(str(minutes) + ':{:02d}'.format(seconds)) # Чтобы не "вырывать" язычок слайдера из рук пользователя, # проверяем, что пользователь НЕ взаимодейтсвует с таймлайном. if not self.is_timeline_dragged: self.timeline.setValue(minutes * 60 + seconds) def loop_or_unloop_current_track(self): """Мини-функция для зацикливания данного трека""" if not self.is_looped_current_track: # Зацикливаем self.is_looped_current_track = True self.queue.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) # Меняем картинку на перечёркнутый круг self.loopBtn.setStyleSheet('background-image: url(icons/unloop.png)') else: # убираем цикл self.is_looped_current_track = False self.queue.setPlaybackMode(self.playlist_handler.mode) self.loopBtn.setStyleSheet('background-image: url(icons/loop.png)') def next_audio(self): """Функция для перемотки на следующий в списке трек""" if self.queue.mediaCount() - 1 == self.queue.currentIndex(): # Если трек ппоследний в списке, возвращаемся к первому self.queue.setCurrentIndex(0) else: # Иначе просто перемещаемся к следующему self.queue.next() def prev_audio(self): """Функция для перемотки на предыдущий в списке трек""" if 0 == self.queue.currentIndex(): # Если трек первый в списке, возвращаемся к последнему self.queue.setCurrentIndex(self.queue.mediaCount() - 1) else: # Иначе просто возвращаемся к предыдущему self.queue.previous() def play_or_pause(self): """Функция для запуска или остановки проигрывателя""" if self.queue.isEmpty(): # Меняем картинку на стрелочку (проигрывание) self.is_playing = False self.playBtn.setStyleSheet('background-image: url(icons/play.png)') # Ставим на паузу self.player.pause() return if self.is_playing: # Меняем картинку на стрелочку (проигрывание) self.is_playing = False self.playBtn.setStyleSheet('background-image: url(icons/play.png)') # Ставим на паузу self.player.pause() else: # Меняем картинку на 2 палочки (пауза) self.is_playing = True self.playBtn.setStyleSheet('background-image: url(icons/pause.png)') # Запускаем звук self.player.play() def change_volume(self): """Мини-Функция для передачи уровня громкости в плеер""" # Функцию использует несколько объектов сразу, проверяем вызывателя if self.sender() == self.volumeBtn: # Если функцию вызвала кнопка, то включаем/выключаем отображение слайдера if not self.volumeSlider.isHidden(): self.volumeSlider.hide() else: self.volumeSlider.show() else: # Иначе функцию вызвал сам слайдер. Значит, меняем значение self.player.setVolume(self.volumeSlider.value()) self.equalizer.setValue(self.volumeSlider.value())
class Window(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super().__init__(parent) # load config self.data = yaml_loader() # load ui self.setupUi(self) # load icons self.setWindowTitle("Sputofy") self.setWindowIcon(QIcon(os.path.join(RES_PATH, "logo.svg"))) loopIcon = QIcon() loopIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "loopIconOFF.svg"))) self.loopBtn.setIcon(loopIcon) prevIcon = QIcon() prevIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "backwardIcon.svg"))) self.prevBtn.setIcon(prevIcon) playIcon = QIcon() playIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "playIcon.svg"))) self.playBtn.setIcon(playIcon) nextIcon = QIcon() nextIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "forwardIcon.svg"))) self.nextBtn.setIcon(nextIcon) randomIcon = QIcon() randomIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "randomIconOFF.svg"))) self.randomBtn.setIcon(randomIcon) volumeIcon = QIcon() volumeIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "volumeIcon.svg"))) self.volumeBtn.setIcon(volumeIcon) # window's settings self.xCor = self.data['last_position']['xPos'] self.yCor = self.data['last_position']['yPos'] self.widthSize = self.data['last_window_size']['width'] self.heightSize = self.data['last_window_size']['height'] self.setGeometry(self.xCor, self.yCor, self.widthSize, self.heightSize) # load YouTubeToMP3 self.YouTubeToMP3 = YouTubeToMP3Window() # open YouTubeToMP3 using button self.actionYT_MP3.triggered.connect(self.YouTubeToMP3.show_window) # info action self.actionInfo.triggered.connect(self.info_handle) #=========================== mediaplayer ============================== # create media player object self.mediaPlayer = QMediaPlayer(None) # open button self.actionOpen_Song.triggered.connect(self.open_song) self.actionOpen_Folder.triggered.connect(self.open_folder) # play button self.playBtn.setEnabled(False) self.playBtn.clicked.connect( self.play_video ) # when btn is pressed: if it is playing it pause, if it is paused it plays # QShortcut(QKeySequence("Space"), self).activated.connect(self.play_video)metodo da ricordare in caso di problemi #TODO # duration slider self.durationSlider.setEnabled(False) self.durationSliderMaxValue = 0 self.durationSlider.valueChanged.connect( self.mediaPlayer.setPosition ) # set mediaPlayer position using the value took from the slider QShortcut('Right', self, lambda: self.durationSlider.setValue( self.durationSlider.value() + 10000)) # 1s = 1000ms QShortcut('Left', self, lambda: self.durationSlider.setValue( self.durationSlider.value() - 10000)) # 1s = 1000ms QShortcut('Shift+Right', self, lambda: self.durationSlider.setValue( self.durationSliderMaxValue - 1000)) # jump to the end-1s of song QShortcut('Shift+Left', self, lambda: self.durationSlider.setValue(0)) # restart song # volumeSlider self.volumeSlider.setProperty("value", 100) self.volumeSlider.setRange(0, 100) self.volumeSlider.setValue( self.data['volume'] if self.data['volume'] != 0 else self.data['volume'] + 1 ) # set slider value | if saved volume is equal to 0 load with volume = 1 else load the saved volume self.mediaPlayer.setVolume( self.data['volume'] if self.data['volume'] != 0 else self.data['volume'] + 1 ) # set mediaPlayer volume | if saved volume is equal to 0 load with volume = 1 else load the saved volume self.volumeLabel.setText( f"{self.data['volume']}%" if self.data['volume'] != 0 else f"{self.data['volume']+1}%" ) # set volume label text | if saved volume is equal to 0 load with volume = 1 else load the saved volume self.volumeSlider.valueChanged.connect( self.mediaPlayer.setVolume ) # set mediaPlayer volume using the value took from the slider QShortcut('Up', self, lambda: self.volumeSlider.setValue( self.volumeSlider.value() + 1)) # volume + 1 QShortcut('Down', self, lambda: self.volumeSlider.setValue( self.volumeSlider.value() - 1)) # volume - 1 QShortcut( 'Shift+Up', self, lambda: self.volumeSlider.setValue(100)) # set maximum volume QShortcut( 'Shift+Down', self, lambda: self.volumeSlider.setValue(0)) # set minimun volume(mute) # volumeBtn self.volumeBtn.clicked.connect( self.volume_toggle) # mute/unmute volume pressing btn self.isMuted = False # starting with a non-muted volume self.previousVolume = self.data[ 'volume'] # loading last registered volume # media player signals self.mediaPlayer.durationChanged.connect( self.duration_changed) # set range of duration slider self.mediaPlayer.positionChanged.connect( self.position_changed) # duration slider progress self.mediaPlayer.stateChanged.connect( self.player_state) # see when it's playing or in pause self.mediaPlayer.volumeChanged.connect( self.volume_icon) # change volumebtn icon #=========================== playlist ============================== # create the playlist self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(2) self.mediaPlayer.setPlaylist(self.playlist) # clear the playlist self.playlistIsEmpty = True # playlistList model self.model = PlaylistModel(self.playlist) self.playlistView.setModel(self.model) self.playlist.currentIndexChanged.connect( self.playlist_position_changed) selection_model = self.playlistView.selectionModel() selection_model.selectionChanged.connect( self.playlist_selection_changed) #=========================== playlist function ============================== self.mediaList = [] # array of loaded songs self.currentPlaylist = "" # current loaded playlist name self.isCustomPlaylist = False # add song name on title self.playlist.currentMediaChanged.connect(self.set_title) # playlist buttons self.nextBtn.clicked.connect(self.next_song) # seek track forward self.prevBtn.clicked.connect(self.prev_song) # seek track backward self.mediaPlayer.mediaStatusChanged.connect( self.auto_next_track ) # once song is ended seek track forward and play it self.actionLoopIt.triggered.connect( self.loop_song) # (1) loop the same song self.actionShuffle.triggered.connect( self.shuffle_playlist) # change song's order self.loopBtn.clicked.connect(self.loop) # (3) loop the playlist self.randomBtn.clicked.connect( self.random) # (4) play random song without end # create new playlist self.actionCreatePlaylist.triggered.connect(self.custom_playlist) # delete current playlist self.actionDeletePlaylist.triggered.connect(self.delete_playlist) # remove all songs self.actionClearQueue.triggered.connect(self.clear_queue) # load playlist self.actionDict = {} # dictionary of action Objects for action in self.data['playlistList']: self.actionDict[action] = self.menuPlaylist.addAction( action, partial(self.load_playlist, action)) if len(self.data['playlistList']) == 0: self.menuPlaylist.menuAction().setVisible(False) #================== Songs opening ==================# def open_folder(self): foldername = QFileDialog.getExistingDirectory(self, "Open folder", "c:\\") if foldername: self.playlist.clear() self.mediaList.clear() for song in os.listdir(foldername): media = f"{foldername}/{song}" self.playlist.addMedia(QMediaContent(QUrl(media))) self.mediaList.append(media) self.playlist.setCurrentIndex(0) self.playBtn.setEnabled(True) self.durationSlider.setEnabled(True) self.playlistIsEmpty = False self.isCustomPlaylist = False self.model.layoutChanged.emit() # load songs in list view self.set_title() self.mediaPlayer.pause() # adjust play/pause icon def open_song(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Song", "c:\\") if filename: if self.playlistIsEmpty == False: self.playlist.clear() self.mediaList.clear() self.playlistIsEmpty = True self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(filename))) self.mediaList.append(filename) self.playBtn.setEnabled(True) self.durationSlider.setEnabled(True) self.isCustomPlaylist = False self.model.layoutChanged.emit() # load song in list view self.set_title() # adjust play/pause icon if self.playlist.mediaCount( ) == 1: # if there is 1 song and you add another self.playlist.setCurrentIndex(0) self.mediaPlayer.pause() def load_playlist(self, playlistName): self.playlist.clear() self.mediaList.clear() # reload config self.data = yaml_loader() for song in self.data['playlistList'][playlistName]: self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(song))) self.mediaList.append(song) self.playlist.setCurrentIndex(0) self.playBtn.setEnabled(True) self.durationSlider.setEnabled(True) self.playlistIsEmpty = False self.isCustomPlaylist = True self.model.layoutChanged.emit() # load songs in list view self.currentPlaylist = playlistName # name of current loaded playlist self.set_title() self.statusbar.showMessage(f'Playlist "{playlistName}" loaded', 4000) self.menuPlaylist.menuAction().setVisible(True) # adjust play/pause icon self.mediaPlayer.pause() def set_title(self): if self.playlist.mediaCount() == 0: self.setWindowTitle("Sputofy") else: if self.isCustomPlaylist == False: self.setWindowTitle( f"Sputofy - {os.path.splitext(self.playlist.currentMedia().canonicalUrl().fileName())[0]} - {self.playlist.currentIndex()+1}/{self.playlist.mediaCount()}" ) else: self.setWindowTitle( f"Sputofy - {self.currentPlaylist} - {os.path.splitext(self.playlist.currentMedia().canonicalUrl().fileName())[0]} - {self.playlist.currentIndex()+1}/{self.playlist.mediaCount()}" ) #=======================================================# #================== Player Functions ==================# def play_video(self): if self.durationSlider.isEnabled(): # if slider was enabled if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def duration_changed(self, duration): self.durationSlider.setRange(0, duration) if duration > 0: self.totalTime_Label.setText(time_format(round( duration / 1000))) # duration is in ms self.durationSliderMaxValue = duration def position_changed(self, position): if position >= 0: self.elapsedTime_Label.setText(time_format( (position / 1000))) # position is in ms # Disable the events to prevent updating triggering a setPosition event (can cause stuttering). self.durationSlider.blockSignals(True) self.durationSlider.setValue(position) self.durationSlider.blockSignals(False) #=======================================================# #================== Playlist Settings ==================# #TODO Work in progress def playlist_array(self): index = self.playlist.mediaCount() mediaList = [] for i in range(index): # songPath = (self.playlist.media(path).canonicalUrl().path())#.split("/",1)[1] # mediaList.append(songPath) # print(self.playlist.media(i).canonicalUrl().path()) mediaList.append(self.playlist.media(i).canonicalUrl().fileName()) return mediaList def custom_playlist(self): if not self.playlist.mediaCount() == 0: name, is_notEmpty = QInputDialog.getText(self, "playlist", "save playlist as:") if name: if name in self.data['playlistList']: self.statusbar.showMessage( "playlist not created (name is already used)", 4000) else: self.data['playlistList'][name] = self.mediaList yaml_dump(self.data) # add new action Object to dictionary self.actionDict[name] = self.menuPlaylist.addAction( name, partial(self.load_playlist, name)) self.load_playlist( name) # instantly loading the new playlist else: self.statusbar.showMessage( "playlist not created (you should give a name to your baby :/)", 4000) else: self.statusbar.showMessage("there are no songs to playlist", 4000) def delete_playlist(self): if self.isCustomPlaylist: if len(self.data['playlistList']) == 1: self.menuPlaylist.menuAction().setVisible(False) self.data['playlistList'].pop( self.currentPlaylist) # remove playlist from dictionary self.menuPlaylist.removeAction(self.actionDict[ self.currentPlaylist]) # remove relative action self.actionDict.pop( self.currentPlaylist) # remove relative action Object self.playlist.clear() self.model.layoutChanged.emit() self.setWindowTitle("Sputofy") yaml_dump(self.data) self.statusbar.showMessage( 'succesfully deleted "' + self.currentPlaylist + '" playlist', 4000) else: self.statusbar.showMessage("cannot delete a non custom playlist", 4000) def clear_queue(self): self.playlist.clear() self.mediaList.clear() self.playBtn.setEnabled(False) self.model.layoutChanged.emit() def playlist_position_changed(self, i): if i > -1: ix = self.model.index(i) self.playlistView.setCurrentIndex(ix) def playlist_selection_changed(self, ix): # We receive a QItemSelection from selectionChanged. i = ix.indexes()[0].row() self.posizione = i self.playlist.setCurrentIndex(i) self.mediaPlayer.play() #=======================================================# #================== Playback Settings ==================# def next_song(self): if self.playlist.currentIndex() == self.playlist.mediaCount() - 1: self.playlist.setCurrentIndex(0) else: self.playlist.next() def prev_song(self): if self.playlist.currentIndex() == 0: self.playlist.setCurrentIndex(self.playlist.mediaCount() - 1) else: self.playlist.previous() def loop_song(self): if self.playlist.playbackMode() != 1: self.playlist.setPlaybackMode(1) self.actionLoopIt.setText("Loop it: ON") self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconOFF.svg"))) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconOFF.svg"))) else: self.playlist.setPlaybackMode(2) self.actionLoopIt.setText("Loop it: OFF") def shuffle_playlist(self): if self.playlist.mediaCount(): self.playlist.shuffle() self.model.layoutChanged.emit() else: self.statusbar.showMessage("there are no songs to shuffle", 4000) def loop(self): if self.playlist.playbackMode() != 3: self.playlist.setPlaybackMode(3) self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconON.svg"))) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconOFF.svg"))) self.actionLoopIt.setText("Loop it: OFF") else: self.playlist.setPlaybackMode(2) self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconOFF.svg"))) def random(self): if self.playlist.playbackMode() != 4: self.playlist.setPlaybackMode(4) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconON.svg"))) self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconOFF.svg"))) self.actionLoopIt.setText("Loop it: OFF") else: self.playlist.setPlaybackMode(2) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconOFF.svg"))) def auto_next_track(self): if self.mediaPlayer.mediaStatus() == QMediaPlayer.EndOfMedia: if self.playlist.playbackMode() == 2: # index starts from 0 mediacount starts from 1 if self.playlist.currentIndex( ) != self.playlist.mediaCount() - 1: self.playlist.next() self.mediaPlayer.play() else: # if ended song was the last one set the index to the first one and pause self.playlist.setCurrentIndex(0) self.mediaPlayer.pause() # loop playlist elif self.playlist.playbackMode() == 3: self.playlist.next() self.mediaPlayer.play() # random song elif self.playlist.playbackMode() == 4: while self.playlist.previousIndex( ) == self.playlist.currentIndex( ): # preventing repeating the same song self.playlist.setCurrentIndex( random.randint(0, self.playlist.mediaCount() - 1)) #=======================================================# #================== Volume Settings ==================# def volume_icon(self, volume): self.volumeLabel.setText(f"{volume}%") if volume: volumeIcon = QIcon() volumeIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "volumeIcon.svg")), QIcon.Normal, QIcon.Off) self.volumeBtn.setIcon(volumeIcon) self.previousVolume = self.volumeSlider.value() self.isMuted = False else: volumeMutedIcon = QIcon() volumeMutedIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "volumeMutedIcon.svg")), QIcon.Normal, QIcon.Off) self.volumeBtn.setIcon(volumeMutedIcon) self.isMuted = True def volume_toggle(self): if self.isMuted == False: self.volumeSlider.setValue(0) self.isMuted = True elif self.isMuted == True: if self.previousVolume == 0: self.volumeSlider.setValue(10) else: self.volumeSlider.setValue(self.previousVolume) self.isMuted = False #=======================================================# def mousePressEvent(self, event): ''' remove the border around the buttons created by using tab key ''' focused_widget = QtWidgets.QApplication.focusWidget() try: focused_widget.clearFocus() except: pass QMainWindow.mousePressEvent(self, event) def player_state(self, event): ''' event handler that adjust the play/pause icon ''' if event == QMediaPlayer.PlayingState: pauseIcon = QIcon() pauseIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "pauseIcon.svg")), QIcon.Normal, QIcon.Off) self.playBtn.setIcon(pauseIcon) elif event == QMediaPlayer.PausedState: playIcon = QIcon() playIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "playIcon.svg")), QIcon.Normal, QIcon.Off) self.playBtn.setIcon(playIcon) def closeEvent(self, event): ''' event handler that take window information and save it in config before the window close ''' # retrieve position xAxis = self.geometry().x() yAxis = self.geometry().y() self.data['last_position']['xPos'] = xAxis self.data['last_position']['yPos'] = yAxis # retrieve size width = self.width() height = self.height() self.data['last_window_size']['width'] = width self.data['last_window_size']['height'] = height # retrieve volume self.data['volume'] = self.mediaPlayer.volume() # retrieve user user = os.getlogin() self.data[ 'default_folder'] = f"C:\\Users\\{user}\\Desktop\\sputofy_songs" yaml_dump(self.data) def info_handle(self): info = "Sputofy\n1.0.0\n©2020 "+\ "Sputofy is a free audio player based on the converted youtube songs made by a_str0\n\n"+\ "Sputofy is written using python 3.x and PyQt5 modules" msg = QMessageBox.about(self, "About", info)
class QgsFmvPlayer(QMainWindow, Ui_PlayerWindow): """ Video Player Class """ def __init__(self, iface, path=None, parent=None): """ Constructor """ super(QgsFmvPlayer, self).__init__(parent) self.setupUi(self) self.parent = parent self.iface = iface self.fileName = None self.metadataDlg = None self.createingMosaic = False self.currentInfo = 0.0 self.RecGIF = QMovie(":/imgFMV/images/record.gif") self.videoWidget.customContextMenuRequested[QPoint].connect( self.contextMenuRequested) self.duration = 0 self.playerMuted = False self.HasFileAudio = False self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.player.setNotifyInterval(1000) # One second self.pass_time = 0.1 self.playlist = QMediaPlaylist() # self.player.setVideoOutput( # self.videoWidget) # Standar Surface self.player.setVideoOutput( self.videoWidget.videoSurface()) # Custom Surface self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.stateChanged.connect(self.setCurrentState) self.playerState = QMediaPlayer.StoppedState self.playFile(path) self.sliderDuration.setRange(0, self.player.duration() / 1000) self.volumeSlider.setValue(self.player.volume()) self.volumeSlider.enterEvent = self.showVolumeTip if self.metadataDlg is None: self.metadataDlg = QgsFmvMetadata(parent=self, player=self) self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg) self.metadataDlg.setMinimumWidth(500) self.metadataDlg.hide() def HasMetadata(self, videoPath): """ Check if video have Metadata or not """ try: p = _spawn([ '-i', videoPath, '-map', 'data-re', '-codec', 'copy', '-f', 'data', '-' ]) stdout_data, _ = p.communicate() if stdout_data == b'': qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "This video don't have Metadata ! : "), level=QGis.Info) return False return True except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "Metadata Callback Failed! : "), str(e), level=QGis.Info) def HasAudio(self, videoPath): """ Check if video have Metadata or not """ try: p = _spawn([ '-i', videoPath, '-show_streams', '-select_streams', 'a', '-loglevel', 'error' ], type="ffprobe") stdout_data, _ = p.communicate() if stdout_data == b'': qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "This video don't have Audio ! : "), level=QGis.Info) return False return True except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "Audio check Failed! : "), str(e), level=QGis.Info) def callBackMetadata(self, currentTime, nextTime): """ Metadata CallBack """ try: # TODO : Speed this function # stdout_data = _check_output(['-i', self.fileName, # '-ss', currentTime, # '-to', nextTime, # '-f', 'data', '-']) t = callBackMetadataThread(cmds=[ '-i', self.fileName, '-ss', currentTime, '-to', nextTime, '-map', 'data-re', '-f', 'data', '-' ]) t.start() t.join(1) if t.is_alive(): t.p.terminate() t.join() if t.stdout == b'': return for packet in StreamParser(t.stdout): try: self.addMetadata(packet.MetadataList()) UpdateLayers(packet, parent=self, mosaic=self.createingMosaic) self.iface.mapCanvas().refresh() QApplication.processEvents() return except Exception as e: None except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "Metadata Callback Failed! : "), str(e), level=QGis.Info) def addMetadata(self, packet): ''' Add Metadata to List ''' self.clearMetadata() row = 0 for key in sorted(packet.keys()): self.metadataDlg.VManager.insertRow(row) self.metadataDlg.VManager.setItem(row, 0, QTableWidgetItem(str(key))) self.metadataDlg.VManager.setItem( row, 1, QTableWidgetItem(str(packet[key][0]))) self.metadataDlg.VManager.setItem( row, 2, QTableWidgetItem(str(packet[key][1]))) row += 1 self.metadataDlg.VManager.setVisible(False) self.metadataDlg.VManager.resizeColumnsToContents() self.metadataDlg.VManager.setVisible(True) self.metadataDlg.VManager.verticalScrollBar().setSliderPosition( self.sliderPosition) def clearMetadata(self): ''' Clear Metadata List ''' try: self.sliderPosition = self.metadataDlg.VManager.verticalScrollBar( ).sliderPosition() self.metadataDlg.VManager.setRowCount(0) except: None def saveInfoToJson(self): """ Save video Info to json """ if not self.KillAllProcessors(): return out_json, _ = QFileDialog.getSaveFileName(self, "Save File", "", "Json Files (*.json)") if out_json == "": return try: self.VPProbeToJson = Converter() self.VPTProbeToJson = QThread() self.VPProbeToJson.moveToThread(self.VPTProbeToJson) self.VPProbeToJson.finished.connect(self.QThreadFinished) self.VPProbeToJson.error.connect(self.QThreadError) self.VPProbeToJson.progress.connect( self.progressBarProcessor.setValue) self.VPTProbeToJson.start(QThread.LowPriority) QMetaObject.invokeMethod(self.VPProbeToJson, 'probeToJson', Qt.QueuedConnection, Q_ARG(str, self.fileName), Q_ARG(str, out_json)) except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Error saving Json")) self.QThreadFinished("probeToJson", "Closing ProbeToJson") def showVideoInfo(self): ''' Show default probe info ''' try: self.VPProbe = Converter() self.VPTProbe = QThread() self.VPProbe.moveToThread(self.VPTProbe) self.VPProbe.finishedJson.connect(self.QThreadFinished) self.VPProbe.error.connect(self.QThreadError) self.VPProbe.progress.connect(self.progressBarProcessor.setValue) self.VPTProbe.start(QThread.LowPriority) QMetaObject.invokeMethod(self.VPProbe, 'probeShow', Qt.QueuedConnection, Q_ARG(str, self.fileName)) except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Error Info Show")) self.QThreadFinished("probeShow", "Closing Probe") return def state(self): ''' Return Current State ''' return self.playerState def setCurrentState(self, state): ''' Set Current State ''' if state != self.playerState: self.playerState = state if state == QMediaPlayer.StoppedState: self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png")) return def showColorDialog(self): ''' Show Color dialog ''' self.ColorDialog = ColorDialog(parent=self) self.ColorDialog.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint) # Fail if not uncheked self.actionMagnifying_glass.setChecked(False) self.actionZoom_Rectangle.setChecked(False) self.ColorDialog.exec_() return def createMosaic(self, value): ''' Function for create Video Mosaic ''' home = os.path.expanduser("~") qgsu.createFolderByName(home, "QGIS_FMV") homefmv = os.path.join(home, "QGIS_FMV") root, ext = os.path.splitext(os.path.basename(self.fileName)) qgsu.createFolderByName(homefmv, root) self.createingMosaic = value # Create Group CreateGroupByName() return def contextMenuRequested(self, point): ''' Context Menu Video ''' menu = QMenu() # actionColors = menu.addAction( # QCoreApplication.translate("QgsFmvPlayer", "Color Options")) # actionColors.setShortcut("Ctrl+May+C") # actionColors.triggered.connect(self.showColorDialog) actionMute = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Mute/Unmute")) actionMute.setShortcut("Ctrl+May+U") actionMute.triggered.connect(self.setMuted) menu.addSeparator() actionAllFrames = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Extract All Frames")) actionAllFrames.setShortcut("Ctrl+May+A") actionAllFrames.triggered.connect(self.ExtractAllFrames) actionCurrentFrames = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Extract Current Frame")) actionCurrentFrames.setShortcut("Ctrl+May+Q") actionCurrentFrames.triggered.connect(self.ExtractCurrentFrame) menu.addSeparator() actionShowMetadata = menu.addAction( QCoreApplication.translate("QgsFmvPlayer", "Show Metadata")) actionShowMetadata.setShortcut("Ctrl+May+M") actionShowMetadata.triggered.connect(self.OpenQgsFmvMetadata) menu.exec_(self.mapToGlobal(point)) # Start Snnipet FILTERS def grayFilter(self, value): self.UncheckFilters(self.sender(), value) self.videoWidget.SetGray(value) self.videoWidget.UpdateSurface() return def edgeFilter(self, value): self.UncheckFilters(self.sender(), value) self.videoWidget.SetEdgeDetection(value) self.videoWidget.UpdateSurface() return def invertColorFilter(self, value): self.UncheckFilters(self.sender(), value) self.videoWidget.SetInvertColor(value) self.videoWidget.UpdateSurface() return def autoContrastFilter(self, value): self.UncheckFilters(self.sender(), value) self.videoWidget.SetAutoContrastFilter(value) self.videoWidget.UpdateSurface() return def monoFilter(self, value): self.UncheckFilters(self.sender(), value) self.videoWidget.SetMonoFilter(value) self.videoWidget.UpdateSurface() return def magnifier(self, value): self.UncheckUtils(self.sender(), value) self.videoWidget.SetMagnifier(value) self.videoWidget.UpdateSurface() return def zoomRect(self, value): self.UncheckUtils(self.sender(), value) self.videoWidget.SetZoomRect(value) self.videoWidget.UpdateSurface() return def UncheckUtils(self, sender, value): # p = self.player.position() # self.player.setVideoOutput( # self.videoWidget.videoSurface()) # Custom surface # self.player.setPosition(p) QApplication.processEvents() name = sender.objectName() self.actionMagnifying_glass.setChecked( True if name == "actionMagnifying_glass" else False) self.actionZoom_Rectangle.setChecked(True if name == "actionZoom_Rectangle" else False) sender.setChecked(value) return def UncheckFilters(self, sender, value): # p = self.player.position() # self.player.setVideoOutput( # self.videoWidget.videoSurface()) # Custom surface # self.player.setPosition(p) # QApplication.processEvents() name = sender.objectName() self.actionGray.setChecked(True if name == "actionGray" else False) self.actionInvert_Color.setChecked(True if name == "actionInvert_Color" else False) self.actionMono_Filter.setChecked(True if name == "actionMono_Filter" else False) self.actionCanny_edge_detection.setChecked( True if name == "actionCanny_edge_detection" else False) self.actionAuto_Contrast_Filter.setChecked( True if name == "actionAuto_Contrast_Filter" else False) self.videoWidget.SetGray(True if name == "actionGray" else False) self.videoWidget.SetEdgeDetection( True if name == "actionCanny_edge_detection" else False) self.videoWidget.SetInvertColor(True if name == "actionInvert_Color" else False) self.videoWidget.SetMonoFilter(True if name == "actionMono_Filter" else False) self.videoWidget.SetAutoContrastFilter( True if name == "actionAuto_Contrast_Filter" else False) sender.setChecked(value) return # End Snnipet FILTERS def isMuted(self): ''' Is muted video property''' return self.playerMuted def setMuted(self): ''' Muted video ''' if self.player.isMuted(): self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_up.png")) self.player.setMuted(False) self.volumeSlider.setEnabled(True) else: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_off.png")) self.player.setMuted(True) self.volumeSlider.setEnabled(False) return def stop(self): ''' Stop video''' self.player.stop() self.videoWidget.update() return def volume(self): ''' Volume Slider ''' return self.volumeSlider.value() def setVolume(self, volume): ''' Tooltip and set value''' self.player.setVolume(volume) self.showVolumeTip(volume) if 0 < volume <= 30: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_30.png")) elif 30 < volume <= 60: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_60.png")) elif 60 < volume <= 100: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_up.png")) elif volume == 0: self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_off.png")) def EndMedia(self): ''' Button end video position ''' if self.player.isVideoAvailable(): self.player.setPosition(self.player.duration()) self.videoWidget.update() return def StartMedia(self): ''' Button start video position ''' if self.player.isVideoAvailable(): self.player.setPosition(0) self.videoWidget.update() return def forwardMedia(self): ''' Button forward Video ''' forwardTime = int(self.player.position()) + 10 * 1000 if forwardTime > int(self.player.duration()): forwardTime = int(self.player.duration()) self.player.setPosition(forwardTime) def rewindMedia(self): ''' Button rewind Video ''' rewindTime = int(self.player.position()) - 10 * 1000 if rewindTime < 0: rewindTime = 0 self.player.setPosition(rewindTime) def AutoRepeat(self, checked): ''' Button AutoRepeat Video ''' if checked: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) return def showVolumeTip(self, _): ''' Volume Slider Tooltip Trick ''' self.style = self.volumeSlider.style() self.opt = QStyleOptionSlider() self.volumeSlider.initStyleOption(self.opt) rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt, self.style.SC_SliderHandle) self.tip_offset = QPoint(5, 15) pos_local = rectHandle.topLeft() + self.tip_offset pos_global = self.volumeSlider.mapToGlobal(pos_local) QToolTip.showText(pos_global, str(self.volumeSlider.value()) + " %", self) def showMoveTip(self, currentInfo): ''' Player Silder Move Tooptip Trick ''' self.style = self.sliderDuration.style() self.opt = QStyleOptionSlider() self.sliderDuration.initStyleOption(self.opt) rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt, self.style.SC_SliderHandle) self.tip_offset = QPoint(5, 15) pos_local = rectHandle.topLeft() + self.tip_offset pos_global = self.sliderDuration.mapToGlobal(pos_local) tStr = _seconds_to_time(currentInfo) QToolTip.showText(pos_global, tStr, self) def durationChanged(self, duration): ''' Duration video change signal ''' duration /= 1000 self.duration = duration self.sliderDuration.setMaximum(duration) def positionChanged(self, progress): ''' Current Video position change ''' progress /= 1000 if not self.sliderDuration.isSliderDown(): self.sliderDuration.setValue(progress) self.updateDurationInfo(progress) def updateDurationInfo(self, currentInfo): ''' Update labels duration Info and CallBack Metadata ''' duration = self.duration self.currentInfo = currentInfo if currentInfo or duration: totalTime = _seconds_to_time(duration) currentTime = _seconds_to_time(currentInfo) tStr = currentTime + " / " + totalTime nextTime = currentInfo + self.pass_time currentTimeInfo = _seconds_to_time_frac(currentInfo) nextTimeInfo = _seconds_to_time_frac(nextTime) # Metadata CallBack self.callBackMetadata(currentTimeInfo, nextTimeInfo) else: tStr = "" self.labelDuration.setText(tStr) def handleCursor(self, status): ''' Change cursor ''' if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia): self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def statusChanged(self, status): ''' Signal Status video change ''' self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.videoAvailableChanged(False) elif status == QMediaPlayer.StalledMedia: self.videoAvailableChanged(False) if status == QMediaPlayer.EndOfMedia: self.videoAvailableChanged(True) elif status == QMediaPlayer.InvalidMedia: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", self.player.errorString()), level=QGis.Warning) self.videoAvailableChanged(False) else: self.videoAvailableChanged(True) def playFile(self, videoPath): ''' Play file from path ''' try: RemoveVideoLayers() RemoveGroupByName() self.fileName = videoPath self.playlist = QMediaPlaylist() url = QUrl.fromLocalFile(videoPath) self.playlist.addMedia(QMediaContent(url)) self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.player.setPlaylist(self.playlist) self.setWindowTitle("Playing : " + os.path.basename(os.path.normpath(videoPath))) if self.HasMetadata(videoPath): CreateVideoLayers() self.clearMetadata() self.lb_cursor_coord.setText( "<span style='font-size:10pt; font-weight:bold;'>Lon :</span>" + "<span style='font-size:9pt; font-weight:normal;'>Null</span>" + "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>" + "<span style='font-size:9pt; font-weight:normal;'>Null</span>" ) else: self.btn_GeoReferencing.setEnabled(False) self.HasFileAudio = True if not self.HasAudio(videoPath): self.actionAudio.setEnabled(False) self.actionSave_Audio.setEnabled(False) self.HasFileAudio = False self.playClicked(True) except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", 'Open Video File : '), str(e), level=QGis.Warning) def ReciconUpdate(self, frame): self.btn_Rec.setIcon(QIcon(self.RecGIF.currentPixmap())) def RecordVideo(self, value): ''' Cut Video ''' currentTime = _seconds_to_time(self.currentInfo) if value is False: self.endRecord = currentTime _, file_extension = os.path.splitext(self.fileName) out, _ = QFileDialog.getSaveFileName(self, "Save As", "", file_extension) if not out: self.RecGIF.frameChanged.disconnect(self.ReciconUpdate) self.RecGIF.stop() self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png")) return False lfn = out.lower() if not lfn.endswith((file_extension)): out += file_extension p = _spawn([ '-i', self.fileName, '-ss', self.startRecord, '-to', self.endRecord, '-c', 'copy', out ]) p.communicate() qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Save file succesfully!")) self.RecGIF.frameChanged.disconnect(self.ReciconUpdate) self.RecGIF.stop() self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png")) else: self.startRecord = currentTime self.RecGIF.frameChanged.connect(self.ReciconUpdate) self.RecGIF.start() return def videoAvailableChanged(self, available): ''' Buttons for video available ''' # self.btn_Color.setEnabled(available) self.btn_CaptureFrame.setEnabled(available) self.gb_PlayerControls.setEnabled(available) return def toggleGroup(self, state): ''' Toggle GroupBox ''' sender = self.sender() if state: sender.setFixedHeight(sender.sizeHint().height()) else: sender.setFixedHeight(15) def playClicked(self, state): ''' Stop and Play video ''' if self.playerState in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.btn_play.setIcon(QIcon(":/imgFMV/images/pause.png")) self.player.play() elif self.playerState == QMediaPlayer.PlayingState: self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png")) self.player.pause() def seek(self, seconds): '''Slider Move''' self.player.setPosition(seconds * 1000) self.showMoveTip(seconds) def convertVideo(self): '''Convert Video To Other Format ''' if not self.KillAllProcessors(): return sel = "mp4 Files (*.mp4)" out, _ = QFileDialog.getSaveFileName( self, "Save Video as...", None, "ogg files (*.ogg);;avi Files (*.avi);;mkv Files (*.mkv);;webm Files (*.webm);;flv Files (*.flv);;mov Files (*.mov);;mp4 Files (*.mp4);;mpg Files (*.mpg);;mp3 Files (*.mp3)", sel) if not out: return False lfn = out.lower() if not lfn.endswith(('.ogg', '.avi', '.mkv', '.webm', '.flv', '.mov', '.mp4', '.mp3', '.mpg')): # The default. out += '.mp4' try: self.VPConverter = Converter() self.VPTConverter = QThread() self.VPConverter.moveToThread(self.VPTConverter) self.VPConverter.finished.connect(self.QThreadFinished) self.VPConverter.error.connect(self.QThreadError) self.VPConverter.progress.connect( self.progressBarProcessor.setValue) self.VPTConverter.start(QThread.LowPriority) # TODO : Make Correct format Conversion and embebed metadata info = self.VPConverter.probeInfo(self.fileName) if info is not None: if self.HasFileAudio: audio_codec = info.audio.codec audio_samplerate = info.audio.audio_samplerate audio_channels = info.audio.audio_channels video_codec = info.video.codec video_width = info.video.video_width video_height = info.video.video_height video_fps = info.video.video_fps _, out_ext = os.path.splitext(out) if self.HasFileAudio: options = { 'format': out_ext[1:], 'audio': { 'codec': audio_codec, 'samplerate': audio_samplerate, 'channels': audio_channels }, 'video': { 'codec': video_codec, 'width': video_width, 'height': video_height, 'fps': video_fps } } else: options = { 'format': out_ext[1:], 'video': { 'codec': video_codec, 'width': video_width, 'height': video_height, 'fps': video_fps } } QMetaObject.invokeMethod(self.VPConverter, 'convert', Qt.QueuedConnection, Q_ARG(str, self.fileName), Q_ARG(str, out), Q_ARG(dict, options), Q_ARG(bool, False)) except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Error converting video ")) self.QThreadFinished("convert", "Closing convert") def ShowPlot(self, bitrate_data, frame_count, output=None): ''' Show plot,because show not work using threading ''' matplot.figure().canvas.set_window_title(self.fileName) matplot.title("Stream Bitrate vs Time") matplot.xlabel("Time (sec)") matplot.ylabel("Frame Bitrate (kbit/s)") matplot.grid(True) # map frame type to color frame_type_color = { # audio 'A': 'yellow', # video 'I': 'red', 'P': 'green', 'B': 'blue' } global_peak_bitrate = 0.0 global_mean_bitrate = 0.0 # render charts in order of expected decreasing size for frame_type in ['I', 'P', 'B', 'A']: # skip frame type if missing if frame_type not in bitrate_data: continue # convert list of tuples to numpy 2d array frame_list = bitrate_data[frame_type] frame_array = numpy.array(frame_list) # update global peak bitrate peak_bitrate = frame_array.max(0)[1] if peak_bitrate > global_peak_bitrate: global_peak_bitrate = peak_bitrate # update global mean bitrate (using piecewise mean) mean_bitrate = frame_array.mean(0)[1] global_mean_bitrate += mean_bitrate * \ (len(frame_list) / frame_count) # plot chart using gnuplot-like impulses matplot.vlines(frame_array[:, 0], [0], frame_array[:, 1], color=frame_type_color[frame_type], label="{} Frames".format(frame_type)) self.progressBarProcessor.setValue(90) # calculate peak line position (left 15%, above line) peak_text_x = matplot.xlim()[1] * 0.15 peak_text_y = global_peak_bitrate + \ ((matplot.ylim()[1] - matplot.ylim()[0]) * 0.015) peak_text = "peak ({:.0f})".format(global_peak_bitrate) # draw peak as think black line w/ text matplot.axhline(global_peak_bitrate, linewidth=2, color='black') matplot.text(peak_text_x, peak_text_y, peak_text, horizontalalignment='center', fontweight='bold', color='black') # calculate mean line position (right 85%, above line) mean_text_x = matplot.xlim()[1] * 0.85 mean_text_y = global_mean_bitrate + \ ((matplot.ylim()[1] - matplot.ylim()[0]) * 0.015) mean_text = "mean ({:.0f})".format(global_mean_bitrate) # draw mean as think black line w/ text matplot.axhline(global_mean_bitrate, linewidth=2, color='black') matplot.text(mean_text_x, mean_text_y, mean_text, horizontalalignment='center', fontweight='bold', color='black') matplot.legend() if output != "": matplot.savefig(output) else: matplot.show() self.progressBarProcessor.setValue(100) def CreateBitratePlot(self): ''' Create video Plot Bitrate Thread ''' if not self.KillAllProcessors(): return try: self.VPBitratePlot = CreatePlotsBitrate() self.VPTBitratePlot = QThread() self.VPBitratePlot.moveToThread(self.VPTBitratePlot) self.VPBitratePlot.finished.connect(self.QThreadFinished) self.VPBitratePlot.return_fig.connect(self.ShowPlot) self.VPBitratePlot.error.connect(self.QThreadError) self.VPBitratePlot.progress.connect( self.progressBarProcessor.setValue) self.VPTBitratePlot.start(QThread.LowPriority) sender = self.sender().objectName() if sender == "actionAudio": QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot', Qt.QueuedConnection, Q_ARG(str, self.fileName), Q_ARG(str, None), Q_ARG(str, 'audio')) elif sender == "actionVideo": QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot', Qt.QueuedConnection, Q_ARG(str, self.fileName), Q_ARG(str, None), Q_ARG(str, 'video')) elif sender == "actionSave_Audio": selfilter = "Portable Network Graphics (*.png)" fileaudio, _ = QFileDialog.getSaveFileName( self, "Save Audio Bitrate Plot", "", "EPS Encapsulated Postscript (*.eps);;" "PGF code for LaTex (*.pgf);;" "Portable document format(*pdf);;" "Portable Network Graphics (*.png);;" "Postscript (*.ps);;" "Raw RGBA bitmap (*.raw*.rgba);;" "Scalable vector graphics (*.svg*.svgz)", selfilter) if fileaudio == "": return QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot', Qt.QueuedConnection, Q_ARG(str, self.fileName), Q_ARG(str, fileaudio), Q_ARG(str, 'audio')) elif sender == "actionSave_Video": selfilter = "Portable Network Graphics (*.png)" filevideo, _ = QFileDialog.getSaveFileName( self, "Save Video Bitrate Plot", "", "EPS Encapsulated Postscript (*.eps);;" "PGF code for LaTex (*.pgf);;" "Portable document format(*pdf);;" "Portable Network Graphics (*.png);;" "Postscript (*.ps);;" "Raw RGBA bitmap (*.raw*.rgba);;" "Scalable vector graphics (*.svg*.svgz)", selfilter) if filevideo == "": return QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot', Qt.QueuedConnection, Q_ARG(str, self.fileName), Q_ARG(str, filevideo), Q_ARG(str, 'video')) except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Failed creating Plot Bitrate")) def ExtractAllFrames(self): """ Extract All Video Frames Thread """ if not self.KillAllProcessors(): return options = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly directory = QFileDialog.getExistingDirectory( self, QCoreApplication.translate("QgsFmvPlayer", "Save images"), '', options=options) if directory: self.VPExtractFrames = ExtractFramesProcessor() self.VPTExtractAllFrames = QThread() self.VPExtractFrames.moveToThread(self.VPTExtractAllFrames) self.VPExtractFrames.finished.connect(self.QThreadFinished) self.VPExtractFrames.error.connect(self.QThreadError) self.VPExtractFrames.progress.connect( self.progressBarProcessor.setValue) self.VPTExtractAllFrames.start(QThread.LowPriority) QMetaObject.invokeMethod(self.VPExtractFrames, 'ExtractFrames', Qt.QueuedConnection, Q_ARG(str, directory), Q_ARG(str, self.fileName)) return def ExtractCurrentFrame(self): """ Extract Current Frame Thread """ image = self.videoWidget.GetCurrentFrame() out_image, _ = QFileDialog.getSaveFileName( self, "Save Current Frame", "", "Image File (*.png *.jpg *.bmp *.tiff)") if out_image == "": return if out_image: t = threading.Thread(target=self.SaveCapture, args=( image, out_image, )) t.start() return def SaveCapture(self, image, output): ''' Save Current Image ''' image.save(output) QApplication.processEvents() return def QThreadFinished(self, process, msg, outjson=None): ''' Finish Threads ''' if process == "ExtractFramesProcessor": self.VPExtractFrames.deleteLater() self.VPTExtractAllFrames.terminate() self.VPTExtractAllFrames.deleteLater() elif process == "CreatePlotsBitrate": self.VPBitratePlot.deleteLater() self.VPTBitratePlot.terminate() self.VPTBitratePlot.deleteLater() elif process == "convert": self.VPConverter.deleteLater() self.VPTConverter.terminate() self.VPTConverter.deleteLater() elif process == "probeToJson": self.VPProbeToJson.deleteLater() self.VPTProbeToJson.terminate() self.VPTProbeToJson.deleteLater() elif process == "probeShow": self.VPProbe.deleteLater() self.VPTProbe.terminate() self.VPTProbe.deleteLater() self.showVideoInfoDialog(outjson) QApplication.processEvents() self.progressBarProcessor.setValue(0) return def QThreadError(self, processor, e, exception_string): """ Threads Errors""" qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", processor), 'Failed!\n'.format(exception_string), level=QGis.Warning) self.QThreadFinished(processor, "Closing Processor") return def OpenQgsFmvMetadata(self): """ Open Metadata Dock """ if self.metadataDlg is None: self.metadataDlg = QgsFmvMetadata(parent=self, player=self) self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg) self.metadataDlg.show() else: self.metadataDlg.show() return def KillAllProcessors(self): """Kill All Processors""" """ Extract all frames Processors """ try: if self.VPTExtractAllFrames.isRunning(): ret = qgsu.CustomMessage( QCoreApplication.translate( "QgsFmvPlayer", "HEY...Active background process!"), QCoreApplication.translate("QgsFmvPlayer", "Do you really want close?")) if ret == QMessageBox.Yes: self.QThreadFinished("ExtractFramesProcessor", "Closing Extract Frames Processor") else: return False except: None """ Bitrates Processors""" try: if self.VPTBitratePlot.isRunning(): ret = qgsu.CustomMessage( QCoreApplication.translate( "QgsFmvPlayer", "HEY...Active background process!"), QCoreApplication.translate("QgsFmvPlayer", "Do you really want close?")) if ret == QMessageBox.Yes: self.QThreadFinished("CreatePlotsBitrate", "Closing Plot Bitrate") else: return False except: None """ Converter Processors """ try: if self.VPTConverter.isRunning(): ret = qgsu.CustomMessage( QCoreApplication.translate( "QgsFmvPlayer", "HEY...Active background process!"), QCoreApplication.translate("QgsFmvPlayer", "Do you really want close?")) if ret == QMessageBox.Yes: self.QThreadFinished("convert", "Closing convert") else: return False except: None """ probeToJson Processors """ try: if self.VPTProbeToJson.isRunning(): ret = qgsu.CustomMessage( QCoreApplication.translate( "QgsFmvPlayer", "HEY...Active background process!"), QCoreApplication.translate("QgsFmvPlayer", "Do you really want close?")) if ret == QMessageBox.Yes: self.QThreadFinished("probeToJson", "Closing Info to Json") else: return False except: None """ probeShow Processors """ try: if self.VPTProbe.isRunning(): ret = qgsu.CustomMessage( QCoreApplication.translate( "QgsFmvPlayer", "HEY...Active background process!"), QCoreApplication.translate("QgsFmvPlayer", "Do you really want close?")) if ret == QMessageBox.Yes: self.QThreadFinished("probeShow", "Closing Show Video Info") else: return False except: None return True def showVideoInfoDialog(self, outjson): """ Show Video Information Dialog """ view = QTreeView() model = QJsonModel() view.setModel(model) model.loadJsonFromConsole(outjson) self.VideoInfoDialog = QDialog(self) self.VideoInfoDialog.setWindowTitle("Video Information : " + self.fileName) self.VideoInfoDialog.setWindowIcon( QIcon(":/imgFMV/images/video_information.png")) self.verticalLayout = QVBoxLayout(self.VideoInfoDialog) self.verticalLayout.addWidget(view) view.expandAll() view.header().setSectionResizeMode(QHeaderView.ResizeToContents) self.VideoInfoDialog.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint) self.VideoInfoDialog.setObjectName("VideoInfoDialog") self.VideoInfoDialog.resize(500, 400) self.VideoInfoDialog.show() def closeEvent(self, evt): """ Close Event """ if self.KillAllProcessors() is False: evt.ignore() return self.player.stop() self.parent._PlayerDlg = None self.parent.ToggleActiveFromTitle() RemoveVideoLayers() RemoveGroupByName() # Restore Filters State self.videoWidget.RestoreFilters() # QApplication.processEvents() del self.player
class Player(QMediaPlayer): player = None # 播放器 playList = None # 播放列表 source = None # 音频路径 content = None # 音频内容 musicSource = [] # 音频路劲列表 MUSIC_PATH = './BackgroundMusic' def __init__(self, parent=None): super(Player, self).__init__(parent) self.getMusicSource() self.initPlayer() self.createPlayList() self.player.play() def getMusicSource(self): """获取音乐文件路径""" for src in os.listdir(self.MUSIC_PATH): self.musicSource.append('{}/{}'.format(self.MUSIC_PATH, src)) def initPlayer(self): """初始化播放器""" self.player = QMediaPlayer(self) # 创建播放器 self.playList = QMediaPlaylist(self.player) # 播放列表 self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) # 播放模式 """ QMediaPlaylist.CurrentItemOnce 0->播放一次 QMediaPlaylist.CurrentItemInLoop 1->单曲循环 QMediaPlaylist.Sequential 2->顺序播放 QMediaPlaylist.Loop 3->列表循环 QMediaPlaylist.Random 4->随机播放 """ def createPlayList(self): """创建播放列表""" self.playList.clear() for path in self.musicSource: self.content = QMediaContent(QUrl.fromLocalFile(path)) self.playList.addMedia(self.content) self.player.setPlaylist(self.playList) # 创建播放列表 # print(self.player.currentMedia().canonicalUrl().path()) # 输出音乐文件路径 def nextMusic(self): """播放下一首音乐""" if self.playList.currentIndex() == len(self.musicSource) - 1: index = 0 else: index = self.playList.currentIndex() + 1 self.playList.setCurrentIndex(index) self.player.play() def previousMusic(self): """播放前一首音乐""" if self.playList.currentIndex() == 0: index = len(self.musicSource) - 1 else: index = self.playList.currentIndex() - 1 self.playList.setCurrentIndex(index) self.player.play() def mute(self): """静音""" self.player.setMuted(True) def cancelMute(self): """取消静音""" self.player.setMuted(False)
__Copyright__ = "Copyright (c) 2015 Irony.\"[讽刺]" __Version__ = "Version 1.0" app = QApplication([]) # 播放列表 playlist = QMediaPlaylist() _list = [] for i in range(1, 12): print("../data/lolita/voice/kiana_%d.mp3" % i) _list.append(QMediaContent(QUrl("../data/lolita/voice/kiana_%d.mp3" % i))) playlist.addMedia(_list) # 只播放当前的 playlist.setPlaybackMode(QMediaPlaylist.CurrentItemOnce) player = QMediaPlayer() # 设置播放列表 player.setPlaylist(playlist) # 设置音量 player.setVolume(100) def play(): playlist.setCurrentIndex(2) player.play() playlist.setCurrentIndex(0) # currentIndex = playlist.currentIndex() + 1 # print(currentIndex) # if currentIndex > playlist.mediaCount():