Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
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())
Esempio n. 4
0
 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
Esempio n. 5
0
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
Esempio n. 6
0
        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()
Esempio n. 7
0
 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
Esempio n. 8
0
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)
Esempio n. 9
0
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)
Esempio n. 10
0
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()
Esempio n. 11
0
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)
Esempio n. 12
0
 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)
Esempio n. 13
0
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)
Esempio n. 14
0
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()
Esempio n. 15
0
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)
Esempio n. 17
0
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()
Esempio n. 18
0
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)
Esempio n. 19
0
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()
Esempio n. 20
0
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']))
Esempio n. 21
0
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()
Esempio n. 22
0
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()
Esempio n. 23
0
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"))
Esempio n. 24
0
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])
Esempio n. 25
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)
Esempio n. 26
0
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()
Esempio n. 27
0
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)
Esempio n. 28
0
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())
Esempio n. 29
0
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))
Esempio n. 30
0
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()
Esempio n. 31
0
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())
Esempio n. 32
0
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)
Esempio n. 33
0
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
Esempio n. 34
0
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)
Esempio n. 35
0
__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():