Ejemplo n.º 1
0
class Player(QGraphicsVideoItem):
    def __init__(self, parent=None):
        super().__init__()
        self.parent = parent

        self.player = QMediaPlayer()
        self.player.setVideoOutput(self)

    def playerPlayOrOpen(self, arg=None):
        if type(arg) == list and len(arg) > 1:
            content = QMediaContent(QUrl.fromLocalFile(arg[1]))
            self.player.setMedia(content)
            self.play()

    def addVideo(self, video):
        content = QMediaContent(QUrl.fromLocalFile(video))
        self.player.setMedia(content)
        self.play()

    def sliderChanged(self, pos):
        self.player.setPosition(pos)

    def mouseDoubleClickEvent(self, event):
        if not self.parent.isFullScreen():
            self.parent.showFullScreen()
        else:
            self.parent.showNormal()

    def play(self):
        self.player.play()

    def stop(self):
        self.player.stop()

    def pause(self):
        self.player.pause()

    def setMuted(self, mute):
        self.player.setMuted(mute)

    def mutedState(self):
        if self.player.isMuted():
            self.setMuted(False)
        else:
            self.setMuted(True)

    def isMuted(self):
        return  self.player.isMuted()

    def setVolume(self, value):
        self.player.setVolume(value)

    def volume(self):
        return self.player.volume()
Ejemplo n.º 2
0
 def __alarm(self):
     if not self.go:
         return;
     self.timer.stop()
     player = QMediaPlayer(self);
     player.setMedia(QMediaContent(QUrl.fromLocalFile(self.music)));
     player.setVolume(100);
     player.play();
     self.setEnabled(False)
     QMessageBox.critical(self, "ALERTA", "TIME TO DIE<br>" + self.ui.groupBox.title(), QMessageBox.Yes)
     self.setEnabled(True)
     player.stop()
     player.deleteLater()
Ejemplo n.º 3
0
class AudioPlayBack():
    def __init__(self):
        self.__audioPlayback = QMediaPlayer()
        self.__audioPlayback.setVolume(50)
        self.__audioPlayback.positionChanged.connect(self.onTick)

        pass

    def onTick(self, e=None):
        print(self.__audioPlayback.position(), self.__audioPlayback.state())
        Event.dis(AudioPlaybackEvent.TICK, self.__audioPlayback.position())
        pass

    def load(self, path):
        content = QMediaContent(QUrl(path))
        self.__audioPlayback.setMedia(content)
        self.__audioPlayback.play()
        pass

    def seek(self, position):
        self.__audioPlayback.setPosition(position)
        pass

    def play(self):
        if self.__audioPlayback.state() == QMediaPlayer.PausedState:
            self.__audioPlayback.play()
            pass
        pass

    def pause(self):
        if self.__audioPlayback.state() == QMediaPlayer.PlayingState:
            self.__audioPlayback.pause()
            pass
        pass

    # 0~100
    def setVolume(self, vol):
        self.__audioPlayback.setVolume(vol)
        pass
Ejemplo n.º 4
0
class IntroWindow(QMainWindow, Form):
    def __init__(self):
        Form.__init__(self)
        QMainWindow.__init__(self)
        self.setWindowIcon(QIcon("logo.png"))

        p = self.palette()
        p.setColor(QPalette.Window, Qt.gray)
        self.setPalette(p)

        self.setupUi(self)

        self.a = 1
        self.videowidget = QVideoWidget()
        self.vertical.addWidget(self.videowidget)
        self.videoplayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.videoplayer.setVideoOutput(self.videowidget)
        self.sliderfilm.setRange(0, 0)
        self.volume.setRange(0, 100)
        self.videoplayer.setVolume(100)
        self.volume.setValue(100)

        self.play.setEnabled(False)
        self.increaseRate.setEnabled(False)
        self.decreaseRate.setEnabled(False)

        self.sliderfilm.installEventFilter(self)
        self.volume.installEventFilter(self)
        self.frames.installEventFilter(self)
        self.frame_2.installEventFilter(self)
        self.frames.installEventFilter(self)

        # putting Icons on buttons

        self.increaseRate.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))
        self.decreaseRate.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekBackward))
        self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.open.setIcon(self.style().standardIcon(QStyle.SP_DirHomeIcon))
        self.skipforward.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))
        self.skipback.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipBackward))
        self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))

        self.sliderfilm.sliderMoved.connect(self.setpos)
        self.videoplayer.positionChanged.connect(self.position)
        self.videoplayer.durationChanged.connect(self.changed)
        self.videoplayer.volumeChanged.connect(self.setvolpos)
        self.volume.sliderMoved.connect(self.setvolpos)
        self.actionOpen.triggered.connect(self.Loadvideo)
        self.actionSearch_By_Tag.triggered.connect(self.opensecond)
        self.actionFullscreen.triggered.connect(self.screen)
        self.skipforward.clicked.connect(self.skipforw)
        self.skipback.clicked.connect(self.skipbac)
        self.increaseRate.clicked.connect(self.incRate)
        self.decreaseRate.clicked.connect(self.decRate)
        self.play.clicked.connect(self.play_video)
        self.open.clicked.connect(lambda: self.Loadvideo(self.videoplayer))
        self.stop.clicked.connect(self.stopp)
        self.listView.hide()
        self.tolfilm = 0
        self.listviewstatus = 0
        self.listbtn.clicked.connect(lambda: self.list())
        self.listView.itemClicked.connect(self.listwidgetclicked)
        self.theme1.triggered.connect(lambda: self.theme01())
        self.theme2.triggered.connect(lambda: self.theme02())
        self.theme3.triggered.connect(lambda: self.theme03())
        self.theme4.triggered.connect(lambda: self.theme04())
        self.actionFarsi.triggered.connect(lambda: self.farsi())
        self.actionEnglish.triggered.connect(lambda: self.english())
        self.filename = ""
        self.x = 0
        self.videowidget3 = QVideoWidget()
        self.verticalLayout_8.addWidget(self.videowidget3)
        self.videoplayer3 = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.videoplayer3.setVideoOutput(self.videowidget3)
        self.widget.hide()
        self.stop.setEnabled(False)
        self.m = 0
        self.dataL = []
        with open("config.txt") as f:
            self.config = f.read()
        if int(self.config) == 11:
            self.theme01()
            self.farsi()
        if int(self.config) == 12:
            self.theme01()
            self.english()
        elif int(self.config) == 21:
            self.farsi()
            self.theme02()
        elif int(self.config) == 22:
            self.english()
            self.theme02()
        elif int(self.config) == 31:
            self.farsi()
            self.theme03()
        elif int(self.config) == 32:
            self.english()
            self.theme03()
        elif int(self.config) == 41:
            self.farsi()
            self.theme04()
        elif int(self.config) == 42:
            self.english()
            self.theme04()

    def farsi(self):
        self.menuLanguage.setTitle("زبان")
        self.menuView.setTitle("نمایش")
        self.theme1.setText("تم ۱")
        self.theme2.setText("تم ۲")
        self.theme3.setText("تم ۳")
        self.theme4.setText("تم ۴")
        self.menuFile.setTitle("فایل")
        self.actionOpen.setText("باز کردن ویدیو")
        self.actionSearch_By_Tag.setText("پنل تگ ها")
        self.actionFullscreen.setText("تمام صفحه")
        self.actionEnglish.setText("انگلیسی")
        self.actionFarsi.setText("فارسی")
        self.decreaseRate.setStatusTip("کاهش سرعت")
        self.decreaseRate.setToolTip("کاهش سرعت")
        self.increaseRate.setStatusTip("افزایش سرعت")
        self.increaseRate.setToolTip("افزایش سرعت")
        self.open.setStatusTip("باز کردن ویدیو")
        self.open.setToolTip("باز کردن ویدیو")
        self.stop.setStatusTip("توقف")
        self.stop.setToolTip("توقف")
        self.skipback.setStatusTip("عقب رفتن")
        self.skipback.setToolTip("عقب رفتن")
        self.play.setStatusTip("شروع/ایست")
        self.play.setToolTip("شروع/ایست")
        self.skipforward.setStatusTip("جلو رفتن")
        self.skipforward.setToolTip("جلو رفتن")
        self.volume.setStatusTip("صدا")
        self.volume.setToolTip("صدا")
        self.listbtn.setStatusTip("دسترسی آسان")
        self.listbtn.setToolTip(
            "پنلی شامل تگ ها و پنجره ای برای پیش نمایش را نمایان/پنهان میکند که با کلیک کردن بر روی هر کدام ویدیو به آن لحظه میرود"
        )
        with open("config.txt") as f:
            self.config = f.read()
        if int(self.config) // 10 == 1:
            with open("config.txt", "w") as f2:
                f2.write("11")
        if int(self.config) // 10 == 2:
            with open("config.txt", "w") as f2:
                f2.write("21")
        if int(self.config) // 10 == 3:
            with open("config.txt", "w") as f2:
                f2.write("31")
        if int(self.config) // 10 == 4:
            with open("config.txt", "w") as f2:
                f2.write("41")

    def english(self):
        self.menuLanguage.setTitle("Language")
        self.menuView.setTitle("View")
        self.theme1.setText("Theme1")
        self.theme2.setText("Theme2")
        self.theme3.setText("Theme3")
        self.theme4.setText("Theme4")
        self.menuFile.setTitle("File")
        self.actionOpen.setText("Open Video")
        self.actionSearch_By_Tag.setText("Tags Panel")
        self.actionFullscreen.setText("Fullscreen")
        self.actionEnglish.setText("English")
        self.actionFarsi.setText("Persian")
        self.decreaseRate.setStatusTip("Decrease Play Speed")
        self.decreaseRate.setToolTip("Decrease Play Speed")
        self.increaseRate.setStatusTip("Increase Play Speed")
        self.increaseRate.setToolTip("Increase Play Speed")
        self.open.setStatusTip("Open Video")
        self.open.setToolTip("Open Video")
        self.stop.setStatusTip("Stop")
        self.stop.setToolTip("Stop")
        self.skipback.setStatusTip("Previous")
        self.skipback.setToolTip("Previous")
        self.play.setStatusTip("Play/Pause")
        self.play.setToolTip("Play/Pause")
        self.skipforward.setStatusTip("Next")
        self.skipforward.setToolTip("Next")
        self.volume.setStatusTip("Volume")
        self.volume.setToolTip("Volume")
        self.listbtn.setStatusTip("Easy Access")
        self.listbtn.setToolTip(
            "Shows/Hides a panel for the tags that can be clicked on to take the video to its moment and also a preview window"
        )
        with open("config.txt") as f:
            self.config = f.read()
            if self.config == "":
                with open("config.txt", w) as f2:
                    f2.write("11")
                    self.config = "11"
        if int(self.config) // 10 == 1:
            with open("config.txt", "w") as f2:
                f2.write("12")
        if int(self.config) // 10 == 2:
            with open("config.txt", "w") as f2:
                f2.write("22")
        if int(self.config) // 10 == 3:
            with open("config.txt", "w") as f2:
                f2.write("32")
        if int(self.config) // 10 == 4:
            with open("config.txt", "w") as f2:
                f2.write("42")

    def moviess(self):
        x = self.filename.split("/")
        file_name = self.filename[:self.filename.find(x[len(x) - 1])]
        png = ""
        png2 = ""
        folders = os.listdir(file_name + r"/")
        for file in folders:
            if file.find(".mp4") > 0:
                png = png + ";" + file_name + file
                png2 = ";" + file_name + file + png2
        png = png + ";"
        self.png = png
        png2 = png2 + ";"
        self.png2 = png2

    def hoverleave(self):
        self.widget.hide()

    def gotovolume(self):
        x, _ = win32api.GetCursorPos()
        self.videoplayer.setVolume(
            int((x - self.mapToGlobal(self.volume.pos()).x()) /
                self.volume.width() * 100))
        self.volume.setValue(
            int((x - self.mapToGlobal(self.volume.pos()).x()) /
                self.volume.width() * 100))
        if self.m % 2 == 1:
            self.m += 1
            self.videoplayer.setMuted(False)

    def goto(self):
        x, _ = win32api.GetCursorPos()
        if self.filename != "":
            self.videoplayer.setPosition(
                (x - self.mapToGlobal(self.sliderfilm.pos()).x()) /
                self.sliderfilm.width() * self.dur * 1000)

    def onHovered(self):
        x, _ = win32api.GetCursorPos()
        if self.filename != "":
            if self.listviewstatus % 2 == 1:
                self.videoplayer3.setPosition(
                    (x - self.mapToGlobal(self.sliderfilm.pos()).x()) /
                    self.sliderfilm.width() * self.dur * 1000)
                self.widget.show()

    def eventFilter(self, obj, event):
        if obj == self.sliderfilm and event.type() == QtCore.QEvent.HoverMove:
            self.onHovered()
        elif (obj == self.frames
              or obj == self.frame_2) and event.type() == QtCore.QEvent.Enter:
            self.hoverleave()
        elif obj == self.sliderfilm and event.type(
        ) == QtCore.QEvent.MouseButtonPress:
            self.goto()
        elif obj == self.volume and event.type(
        ) == QtCore.QEvent.MouseButtonPress:
            self.gotovolume()
        elif obj == self.frames and event.type(
        ) == QtCore.QEvent.MouseButtonDblClick:
            if not self.isFullScreen():
                self.fulls()
            else:
                self.unfull()

        return super(QMainWindow, self).eventFilter(obj, event)

    def stopp(self):
        self.stop.setEnabled(False)
        self.videoplayer.stop()
        self.videoplayer.setPosition(0)
        self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

    def listwidgetclicked(self, item):
        t = item.text()
        t = t[t.find(">") + 1:]
        pt = datetime.strptime(t, "%H:%M:%S")
        total_seconds = pt.second + pt.minute * 60 + pt.hour * 3600
        if self.a == 0:
            self.videoplayer.setPosition(total_seconds * 1000)

    def list(self):
        if self.listviewstatus % 2 == 1:
            self.listView.hide()
            self.widget.hide()
            self.listbtn.setText("^")
            self.listviewstatus += 1
        else:
            self.listbtn.setText("v")
            self.listviewstatus += 1
            self.listView.show()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            if self.isFullScreen():
                self.unfull()
        elif e.key() == Qt.Key_6:
            if self.filename != "":
                self.videoplayer.setPosition(self.videoplayer.position() +
                                             5000)
        elif e.key() == Qt.Key_4:
            if self.filename != "":
                self.videoplayer.setPosition(self.videoplayer.position() -
                                             5000)
        elif e.key() == Qt.Key_Space:
            if self.filename != "":
                self.play_video()
        elif e.key() == Qt.Key_M:
            if self.m % 2 == 0:
                self.m += 1
                self.videoplayer.setMuted(True)
                self.volume.setEnabled(False)
                self.vvv = self.volume.value()
                self.volume.setValue(0)
            else:
                self.m += 1
                self.volume.setValue(self.vvv)
                self.volume.setEnabled(True)
                self.videoplayer.setMuted(False)

    def screen(self):
        if not self.isFullScreen():
            self.fulls()
        else:
            self.unfull()

    # forward media 5s
    def skipforw(self):
        a = self.png.find(self.filename)
        aa = self.png.find(";", a + 1)
        filename = self.png[aa + 1:self.png.find(";", aa + 1)]
        if filename != "":
            self.filename = filename
            self.videoplayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(filename)))
            self.videoplayer3.setMedia(
                QMediaContent(QUrl.fromLocalFile(filename)))
            title = filename.split("/")
            title = title[len(title) - 1]
            self.setWindowTitle(f"Taz Player openning{title}")
            self.videoplayer3.play()
            self.videoplayer3.pause()
            self.widget.hide()
            self.videoplayer.setPosition(0)
            self.videoplayer.play()
            self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
            clip = VideoFileClip(filename)
            self.dur = clip.duration

    def skipbac(self):
        a = self.png2.find(self.filename)
        aa = self.png2.find(";", a + 1)
        filename = self.png2[aa + 1:self.png2.find(";", aa + 1)]
        if filename != "":
            self.filename = filename
            self.videoplayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(filename)))
            self.videoplayer3.setMedia(
                QMediaContent(QUrl.fromLocalFile(filename)))
            title = filename.split("/")
            title = title[len(title) - 1]
            self.setWindowTitle(f"Taz Player openning{title}")
            self.videoplayer3.play()
            self.videoplayer3.pause()
            self.widget.hide()
            self.videoplayer.setPosition(0)
            self.videoplayer.play()
            self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
            clip = VideoFileClip(filename)
            self.dur = clip.duration

        # set increase rate

    def incRate(self):
        if self.videoplayer.playbackRate() == 0:
            x = self.videoplayer.playbackRate() + 1
        else:
            x = self.videoplayer.playbackRate()
        self.videoplayer.setPlaybackRate(x + 0.25)

    # set decrease rate
    def decRate(self):
        if self.videoplayer.playbackRate() == 0:
            x = self.videoplayer.playbackRate() + 1
        else:
            x = self.videoplayer.playbackRate()
        self.videoplayer.setPlaybackRate(x - 0.25)

    # Handling Tags
    def fillListView(self):
        for i in range(len(self.dataL)):
            self.listView.addItem(self.dataL[i][0] + "->" + self.dataL[i][1])

    def updateTagFile(self):
        fname = self.fileName.split(".")
        fname = fname[0]
        with open(fname + ".csv", mode="w") as f:
            writer = csv.writer(
                f,
                delimiter=",",
                quotechar='"',
                quoting=csv.QUOTE_MINIMAL,
                lineterminator="\n",
            )
            for line in self.dataL:
                writer.writerow(line)

    def giveTime(self):
        vidPos = self.videoplayer.position()
        h = int(vidPos / 1000 // 3600)
        m = int((vidPos / 1000 - h * 3600) // 60)
        s = int(((vidPos / 1000 - h * 3600 - m * 60) % 60) % 60) * 100 // 100
        if h < 10:
            h = "0" + str(h)
        if m < 10:
            m = "0" + str(m)
        if s < 10:
            s = "0" + str(s)
        return f"{h}:{m}:{s}"

    def insertTag(self, tableWidget):
        t = tableWidget
        tag = "New Tag"
        tagTime = self.giveTime()
        l = len(self.dataL)
        i = 0
        flag = False

        while tagTime > self.dataL[i][1]:
            i += 1
            if i >= l:
                break

        if i < l:
            if tagTime == self.dataL[i][1]:
                flag = True

        if not flag:
            self.dataL.insert(i, [tag, tagTime])

            t.insertRow(i)
            t.setItem(
                i,
                0,
                QTableWidgetItem(tag),
            )
            t.setItem(
                i,
                1,
                QTableWidgetItem(tagTime),
            )
            t.editItem(t.item(i, 0))

    def removeRow(self, tableWidget):
        if len(self.dataL) > 0:
            self.dataL.remove(self.dataL[tableWidget.currentRow()])
        tableWidget.removeRow(tableWidget.currentRow())

    def updateList(self, tableWidget):
        for i in range(tableWidget.rowCount()):
            self.dataL[i] = [
                tableWidget.item(i, 0).text(),
                tableWidget.item(i, 1).text(),
            ]

    def undoChanges(self):
        fname = self.fileName.split(".")
        fname = fname[0]
        with open(fname + ".csv", mode="r+") as f:
            data = csv.reader(f)
            self.dataL = list(data)

    def fillTable(self, tableWidget):
        tableWidget.setRowCount(len(self.dataL))
        for i in range(len(self.dataL)):
            tableWidget.setItem(i, 0, QTableWidgetItem(self.dataL[i][0]))
            tableWidget.setItem(i, 1, QTableWidgetItem(self.dataL[i][1]))

    def openTagFile(self):
        filename, _ = QFileDialog.getOpenFileName(
            self,
            "Open Tag File",
            filter="*.csv",
        )
        if filename != "":
            self.fileName = filename
            with open(filename, mode="r+") as f:
                data = csv.reader(f)
                self.dataL = list(data)

    def opensecond(self):
        login_page = LoginPage()
        login_page.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
        if int(self.config) % 10 == 1:
            login_page.Save.setText("برو به")
            login_page.apply.setText("اعمال تغییرات")
            login_page.buttonBox.button(QDialogButtonBox.Ok).setText("تایید")
            login_page.buttonBox.button(
                QDialogButtonBox.Cancel).setText("انصراف")
            login_page.AddRow.setText("افزودن تگ")
            login_page.DeleteRow.setText("حذف تگ")
            login_page.OpenTagButton.setText("باز کردن فایل تگ")
            login_page.tableWidget.setHorizontalHeaderLabels(["تگ", "زمان"])
        else:
            login_page.tableWidget.setHorizontalHeaderLabels(["Tag", "Time"])

        self.fillTable(login_page.tableWidget)

        login_page.buttonBox.accepted.connect(lambda: [
            self.updateList(login_page.tableWidget),
            self.listbtn.setFocus(),
            self.listView.clear(),
            self.fillListView(),
            self.updateTagFile(),
        ])

        login_page.buttonBox.rejected.connect(lambda: [
            self.listbtn.setFocus(),
            self.undoChanges(),
        ])

        login_page.apply.clicked.connect(lambda: [
            self.updateList(login_page.tableWidget),
            self.listView.clear(),
            self.fillListView(),
        ])

        login_page.AddRow.clicked.connect(lambda: [
            self.insertTag(login_page.tableWidget),
        ])

        login_page.Save.clicked.connect(lambda: [
            login_page.shows(self),
            self.updateList(login_page.tableWidget),
            self.listbtn.setFocus(),
            self.listView.clear(),
            self.fillListView(),
        ])

        login_page.DeleteRow.clicked.connect(lambda: [
            self.removeRow(login_page.tableWidget),
        ])

        login_page.OpenTagButton.clicked.connect(lambda: [
            self.openTagFile(),
            self.fillTable(login_page.tableWidget),
            self.listView.clear(),
            self.fillListView(),
        ])

        login_page.tableWidget.sortByColumn(1, Qt.AscendingOrder)
        # if int(self.config) % 10 == 2:
        #     login_page.tableWidget.setHorizontalHeaderLabels(["Tag", "Time"])
        # else:
        #     login_page.tableWidget.setHorizontalHeaderLabels(["تگ", "زمان"])

        login_page.exec_()

    # End of Handling Tags

    def fulls(self):
        self.decreaseRate.hide()
        self.increaseRate.hide()
        self.centralwidget.setContentsMargins(0, 0, 0, 0)
        self.play.hide()
        self.open.hide()
        self.skipforward.hide()
        self.skipback.hide()
        self.label.hide()
        self.label_2.hide()
        self.volume.hide()
        self.menubar.hide()
        self.sliderfilm.hide()
        self.statusBar.hide()
        self.showFullScreen()
        self.listbtn.hide()
        self.widget.hide()
        self.listView.hide()
        self.frame_2.hide()
        self.stop.hide()
        self.listviewstatus = 1

    def unfull(self):
        self.frame_2.show()
        self.stop.show()
        self.list()
        self.centralwidget.setContentsMargins(10, 10, 10, 10)
        self.decreaseRate.show()
        self.increaseRate.show()
        self.play.show()
        self.open.show()
        self.skipforward.show()
        self.skipback.show()
        self.label.show()
        self.label_2.show()
        self.volume.show()
        self.menubar.show()
        self.sliderfilm.show()
        self.statusBar.show()
        self.showNormal()
        self.listbtn.show()

    ##setting position of film
    def setpos(self, position):
        self.videoplayer.setPosition(position)

    def position(self, position):
        position2 = self.tolfilm * 1000 - position + 1000
        hour = int((position / 3600000) % 24)
        hour2 = int((position2 / 3600000) % 24)
        if hour < 10:
            hour = "0" + str(hour)
        if hour2 < 10:
            hour2 = "0" + str(hour2)
        minute = int((position / 60000) % 60)
        minute2 = int((position2 / 60000) % 60)
        if minute < 10:
            minute = "0" + str(minute)
        if minute2 < 10:
            minute2 = "0" + str(minute2)
        second = int((position / 1000) % 60)
        second2 = int((position2 / 1000) % 60)
        if second < 10:
            second = "0" + str(second)
        if second2 < 10:
            second2 = "0" + str(second2)
        self.label.setText(f"{hour}:{minute}:{second}")
        self.label_2.setText(f"{hour2}:{minute2}:{second2}")
        self.sliderfilm.setValue(position)
        if position2 < 1000:
            self.videoplayer.stop()
            self.sliderfilm.setValue(0)
            self.stop.setEnabled(False)
            self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

    def changed(self, duration):
        self.sliderfilm.setRange(0, duration)

    ##setting position of volume
    def setvolpos(self, position):
        self.videoplayer.setVolume(position)

    ##open button or open from menu bar
    def Loadvideo(self, videoplayer):
        self.a = 0
        filename, _ = QFileDialog.getOpenFileName(
            self,
            "Open Video",
            filter="*.mp4;*.mov;*.wmv;*.webm;*.wmv;*.m4v;*.m4a;*.flv",
        )
        if filename != "":
            self.videoplayer.setPosition(0)
            self.filename = filename
            if filename != "":
                self.fileName = filename.split(".")[0]
                fname = filename.split(".")
                fnmae = fname[0]
                if os.path.isfile(fnmae + ".csv"):
                    with open(fnmae + ".csv", mode="r+") as f:
                        data = csv.reader(f)
                        self.dataL = list(data)
                        self.listView.clear(),
                        self.fillListView()
                clip = VideoFileClip(filename)
                self.dur = clip.duration
                self.videoplayer.setMedia(
                    QMediaContent(QUrl.fromLocalFile(filename)))
                self.videoplayer3.setMedia(
                    QMediaContent(QUrl.fromLocalFile(filename)))
                self.moviess()
                clip = VideoFileClip(filename)
                self.tolfilm = int(clip.duration)
                title = filename.split("/")
                title = title[len(title) - 1]
                self.setWindowTitle(f"Taz Player openning : {title}")
                self.videoplayer3.play()
                self.videoplayer3.pause()
                self.widget.hide()
                self.stop.setEnabled(True)
                self.videoplayer.play()
                self.play.setEnabled(True)
                self.play.setIcon(self.style().standardIcon(
                    QStyle.SP_MediaPause))
                self.increaseRate.setEnabled(True)
                self.decreaseRate.setEnabled(True)

    ##play button
    def play_video(self):
        if self.videoplayer.state() == QMediaPlayer.PlayingState:
            self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
            self.videoplayer.pause()
        else:
            self.videoplayer.play()
            self.stop.setEnabled(True)
            self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))

    def theme01(self):
        self.videowidget.setStyleSheet("background-color: #404040")
        self.setStyleSheet("background-color: #A0A0A0")
        if self.theme1.text() == "Theme1":
            with open("config.txt", "w") as f:
                f.write("12")
        else:
            with open("config.txt", "w") as f:
                f.write("11")

    def theme02(self):
        self.videowidget.setStyleSheet("background-color: #330019")
        self.setStyleSheet("background-color: #990000")
        if self.theme1.text() == "Theme1":
            with open("config.txt", "w") as f:
                f.write("22")
        else:
            with open("config.txt", "w") as f:
                f.write("21")

    def theme03(self):
        self.videowidget.setStyleSheet("background-color: #35557F")
        self.setStyleSheet("background-color: #003366")
        if self.theme1.text() == "Theme1":
            with open("config.txt", "w") as f:
                f.write("32")
        else:
            with open("config.txt", "w") as f:
                f.write("31")

    def theme04(self):
        self.videowidget.setStyleSheet("background-color: #00FF00")
        self.setStyleSheet("background-color: #4C9900")
        if self.theme1.text() == "Theme1":
            with open("config.txt", "w") as f:
                f.write("42")
        else:
            with open("config.txt", "w") as f:
                f.write("41")
Ejemplo n.º 5
0
class VideoPlayer(QVideoWidget):
    # doubleClicked = pyqtSignal()
    clicked = pyqtSignal()

    # keyPressed = pyqtSignal()
    # rtime_changed = pyqtSignal(str)
    # duration_changed = pyqtSignal(int)

    def __init__(self, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.playing = False
        self.full_screen = False

        self.media_player = QMediaPlayer()

        self.media_player.setVideoOutput(self)

        self.widescreen = True

        self.media_player.setVolume(0)

    def load_video(self, path):
        self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(path)))

    def play(self):
        if self.playing is False:
            self.media_player.play()
            self.playing = True
        else:
            self.media_player.pause()
            self.playing = False

    def stop(self):
        self.media_player.stop()
        self.playing = False

    def set_volume(self, volume):
        self.media_player.setVolume(volume)

    def mousePressEvent(self, event):
        # self.play()
        self.clicked.emit()
        super(VideoPlayer, self).mousePressEvent(event)

    def update_position(self, position):
        self.media_player.setPosition(position)

    def set_postion(self, position):
        self.media_player.setPosition(position)

    def mouseDoubleClickEvent(self, event):
        self.set_fullscreen()

    def set_fullscreen(self):
        self.setFullScreen(not self.isFullScreen())

    def keyPressEvent(self, event):
        if event.key() == Qt.Qt.Key_Escape and self.isFullScreen():
            self.setFullScreen(False)
            event.accept()
        else:
            super(VideoPlayer, self).keyPressEvent(event)
Ejemplo n.º 6
0
class VideoPlayer(QWidget):
    
    def __init__(self, parent=None):
        global gantChart
        global Topics
        
        super(VideoPlayer, self).__init__(parent)
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVolume(0)
        
        #Parse json file
        videoGlobals.classLabels, videoGlobals.highLabels, videoGlobals.annotationColors, videoGlobals.eventColors = self.parseJson()
        
        Topics              = None
        self.time_          = 0
        self.time_dif       = 0
        self.duration       = 0
        self.message_count  = 0
        self.videobox       = []
        self.box_buffer     = []
        self.metric_buffer  = []
        
        #Audio variables
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist(self)
        self.playFlag = False
        
        self.topic_window = topicBox.TopicBox()
        
        # >> DEFINE WIDGETS OCJECTS
        # >> VIDEO - AUDIO - GANTT CHART
        #----------------------
        self.videoWidget = VideoWidget()
        self.videoWidget.setFixedSize(640, 480)

        #Video buttons
        videoLayout = self.createVideoButtons()
                
        #Video Gantt Chart
        self.gantt = gantChart.gantShow()
        gantChart = self.gantt
        gantChart.axes.get_xaxis().set_visible(False)
        gantChart.setFixedSize(1300, 90)
        
        #Create Slider
        self.createSlider()
        
        self.controlEnabled = False

        #Specify video layout align
        laserAndVideoLayout = QHBoxLayout()
        laserAndVideoLayout.addLayout(videoLayout)

        #Audio Player buttons
        buttonLayoutAudio = self.createAudioButtons()
        waveLayout = self.createAudio()
        
        
        self.mainLayout = QVBoxLayout()
        self.mainLayout.addLayout(laserAndVideoLayout)
        self.mainLayout.addWidget(self.positionSlider)
        self.mainLayout.addWidget(self.gantt)
        self.mainLayout.addLayout(waveLayout)
        self.mainLayout.addLayout(buttonLayoutAudio)

        self.setLayout(self.mainLayout)

        self.mediaPlayer.setVideoOutput(self.videoWidget.videoSurface())
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)

    def createSlider(self):
        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setMinimum(0)
        self.positionSlider.setMaximum(self.duration)
        self.positionSlider.setTickInterval(1)
        self.positionSlider.sliderMoved.connect(self.setPosition)

    def createVideoButtons(self):
        
        verticalLine 	=  QFrame()
        verticalLine.setFrameStyle(QFrame.VLine)
        verticalLine.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding)
        
        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setShortcut(QKeySequence(Qt.Key_Space))
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

              
        self.previousButton = QPushButton()
        self.previousButton.setIcon(self.style().standardIcon(QStyle.SP_MediaSeekBackward))
        self.previousButton.setShortcut(QKeySequence(Qt.ALT + Qt.Key_A))
        self.previousButton.clicked.connect(self.previousFrame)
        
        self.nextButton = QPushButton()
        self.nextButton.setIcon(self.style().standardIcon(QStyle.SP_MediaSeekForward))
        self.nextButton.setShortcut(QKeySequence(Qt.ALT + Qt.Key_D))
        self.nextButton.clicked.connect(self.nextFrame)        
        
        
         #add label to slider about elapsed time
        self.label_tmp = '<b><FONT SIZE=3>{}</b>'
        self.timelabel = QLabel(self.label_tmp.format('Time: ' + str(self.duration)))


        self.label = QHBoxLayout()
        self.label.addWidget(self.timelabel)
        self.label.setAlignment(Qt.AlignRight)
        
        
        self.controlLayout = QHBoxLayout()
        self.controlLayout.addWidget(self.playButton)
        self.controlLayout.addWidget(self.previousButton)
        self.controlLayout.addWidget(self.nextButton)
        self.controlLayout.setAlignment(Qt.AlignLeft)
        
        self.newLayout = QHBoxLayout()
        self.newLayout.addLayout(self.controlLayout)
        self.newLayout.addLayout(self.label)
        
        videoLayout = QVBoxLayout()
        videoLayout.addWidget(self.videoWidget)
        videoLayout.addLayout(self.newLayout)
        
        return videoLayout
        
    def pauseMedia(self):
        self.mediaPlayer.pause()
        self.Pause()

    def previousFrame(self):
        global frameCounter
        if frameCounter > 0:
            frameCounter -= 2
            pos = round(((frameCounter ) * (self.duration * 1000)) / self.message_count)
            self.mediaPlayer.setPosition(pos) 
        
    def nextFrame(self):
        global frameCounter
    
        if frameCounter < self.message_count:
            pos = round(((frameCounter ) * (self.duration * 1000)) / self.message_count)
            self.mediaPlayer.setPosition(pos) 
        
    # AUDIO PLAYER BUTTON FUNCTIONS
    def createAudio(self):
        #Define Audio annotations and gantt chart
        self.wave = vA.Waveform()
        audioGlobals.fig = self.wave
        self.wave.axes.get_xaxis().set_visible(False)
        self.wave.draw()
        self.wave.setFixedSize(1300, 175)
        
        self.audioChart = gA.Chart()
        audioGlobals.chartFig = self.audioChart
        self.audioChart.setFixedSize(1300, 90)
        
        #Audio layouts
        waveLayout = QVBoxLayout()
        waveLayout.addWidget(self.wave)
        waveLayout.addWidget(self.audioChart)
        
        return waveLayout
        
    def createAudioButtons(self):
        self.playButtonAudio = QPushButton()
        self.stopButtonAudio = QPushButton()

        self.playButtonAudio.clicked.connect(self.audioPlay)
        
        self.playButtonAudio.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        
        buttonLayoutAudio = QHBoxLayout()
        buttonLayoutAudio.addWidget(self.playButtonAudio)
        buttonLayoutAudio.setAlignment(Qt.AlignLeft)
        
        return buttonLayoutAudio
       
    #Play audio (whole signal or segment)
    def audioPlay(self):

        #GET CLICKS FROM WAVEFORM
        #Initialize connection-position ONCE
        if not audioGlobals.playerStarted:
            #10ms for changePosition -> Not Delaying
            self.player.positionChanged.connect(self.checkPositionToStop)
            self.player.setNotifyInterval(10)
            audioGlobals.playerStarted = True
            if audioGlobals.durationFlag in [0, 1]:
                self.end = audioGlobals.duration*1000 - 10
                audioGlobals.endTimeToPlay = self.end
            else:
                self.end = audioGlobals.endTimeToPlay
                
                
            self.start = audioGlobals.startTimeToPlay
            self.player.setPosition(self.start)
            
       
        if self.playFlag:
            self.playFlag = False
            audioGlobals.playerStarted = True
            self.player.setPosition(self.time_)
            self.player.pause()
            self.playButtonAudio.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        else:
            self.playFlag = True
            self.playButtonAudio.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
            self.player.play()

    #Stop audio playing
    def audioStop(self):
        self.player.stop()
        #Begin again segment
        self.start = audioGlobals.startTimeToPlay
        self.player.setPosition(self.start)

    #Check ms in audio to stop play
    def checkPositionToStop(self):
        self.time_ = self.player.position()
        if not video_player:
            audioGlobals.fig.drawNew(float(self.time_)/1000)
            audioGlobals.fig.draw()
        if self.time_ >= self.end:
            self.audioStop()
            self.player.setPosition(self.start)

    def videoPosition(self):
        self.videoTime = self.mediaPlayer.position()

    def openFile(self):
        global framerate
        global bagFile
        global rgbFileName
        global Topics
        global audio_player
        global video_player
        framerate = 0
               
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Bag", QDir.currentPath(),"(*.bag *.avi *.mp4 *.mkv *.mp3 *.wav)")
        # create a messsage box for get or load data info
        if fileName:
            name, extension = os.path.splitext(fileName)
            self.videobox = []
            if extension == '.bag':
                bagFile = fileName
                try:
                    bag = rosbag.Bag(fileName)
                    Topics, self.duration = get_bag_metadata(bag)
                    #Show window to select topics
                    self.topic_window.show_topics(Topics)
                except:
                    self.errorMessages(0)
                        
                #Audio Handling
                if self.topic_window.temp_topics[0][1] != 'Choose Topic':
                    try:
                        audio_player = True
                        audioGlobals.annotations = []
                        rosbagAudio.runMain(bag, str(fileName))
                    except:
                        self.errorMessages(6)
                    
                    #DEFINE PLAYER-PLAYLIST
                    #----------------------
                    self.source = QUrl.fromLocalFile(os.path.abspath(audioGlobals.wavFileName))
                    self.content = QMediaContent(self.source)
                    self.playlist.addMedia(self.content)
                    self.player.setPlaylist(self.playlist)

                    self.wave.drawWave()
                    self.wave.drawAnnotations()
                    self.wave.draw()
                    self.audioChart.drawChart()
                    self.audioChart.draw()                        
                #RGB Handling
                if self.topic_window.temp_topics[2][1] != 'Choose Topic':
                    try:
                        video_player = True
                        rgbFileName = fileName.replace(".bag","_RGB.avi")

                        if not os.path.isfile(rgbFileName):
                            self.message_count, compressed, framerate = rosbagVideo.buffer_bag_metadata(bag, self.topic_window.temp_topics[2][1])
                            #Get bag video metadata
                            print('Getting rgb data from ROS', 'green')
                            image_buffer = rosbagRGB.buffer_rgb_data(bag, self.topic_window.temp_topics[2][1], compressed)
                            if not image_buffer:
                                raise Exception(8)
                            result  = rosbagRGB.write_rgb_video(rgbFileName, image_buffer, framerate)
                            if not result:
                                raise Exception(2)
                        
                        self.duration, framerate, self.message_count =  rosbagRGB.get_metadata(rgbFileName)
                        
                        # just fill time buffer in case that video exists
                        start_time = None
                        for topic, msg, t in bag.read_messages(topics=[self.topic_window.temp_topics[2][1]]):
                            if not start_time:
                                start_time = t.to_sec()
                            time = t.to_sec() - start_time
                            self.videobox.append(boundBox(time))
                            
                        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(os.path.abspath(rgbFileName))))
                        self.playButton.setEnabled(True)
                     
                                        
                                    
                    except Exception as e:
                        print(e)
                        self.errorMessages(e[0])	                            
            else:
                if extension in video_extensions:
                    video_player = True
                    self.duration, framerate, self.message_count  =  rosbagRGB.get_metadata(fileName)
                    self.videobox = [boundBox(count/framerate) for count in xrange(int(self.message_count))] 
                    self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(os.path.abspath(fileName))))
                    self.playButton.setEnabled(True)
                    rgbFileName = fileName
                
                try:
                    audioGlobals.annotations = []
                    rosbagAudio.runMain(None, str(fileName))
                    
                    #DEFINE PLAYER-PLAYLIST
                    #----------------------
                    print audioGlobals.wavFileName
                    self.source = QUrl.fromLocalFile(os.path.abspath(audioGlobals.wavFileName))
                    self.content = QMediaContent(self.source)
                    self.playlist.addMedia(self.content)
                    self.player.setPlaylist(self.playlist)
        
                    self.wave.drawWave()
                    self.wave.drawAnnotations()
                    self.wave.draw()
                    self.audioChart.drawChart()
                    self.audioChart.draw()
                    audio_player = True
                    
                except:
                    print "No audio found"
                
            
            mainWindow.repaint(player.videobox, framerate)
            mainWindow.setWindowTitle(fileName)    
            self.setWindowTitle(fileName + ' -> Annotation')
     
    #Open CSV file
    def openCsv(self):
        global framerate
        global rgbFileName
        global bagFile
        global videoCSV
        global headlines
        self.box_buffer = []
        
        if rgbFileName is not None:
            
            # OPEN VIDEO - AUDIO
            fileName,_ =  QFileDialog.getOpenFileName(self, "Open Csv ", os.path.dirname(os.path.abspath(rgbFileName)),"(*.csv)")
            if fileName:
                videoCSV = fileName
                self.videobox = [boundBox(count) for count in xrange(int(self.message_count))]
                headlines, box_buff, box_action, features = rosbagRGB.buffer_video_csv(fileName)
                if not (box_buff):
                    self.errorMessages(1)
                else:
                    self.box_buffer = [list(elem) for elem in box_buff]
                    
                    #Frame counter initialize
                    timestamp = None
                    counter = 0
                    self.box_actionBuffer = [key for key in box_action]
                    self.features = [key for key in features]
                    for i, key in enumerate(self.box_buffer):
                        if timestamp is not None:
                            if timestamp != key[0]:
                                counter += 1
                        self.videobox[counter].addBox(key[0], key[1], key[2:], self.box_actionBuffer[i], features[i])
                        timestamp  = key[0]
                              
                    mainWindow.repaint(player.videobox, framerate)
        else:
            self.errorMessages(10)
	
    #Writes the boxes to csv
    def writeCSV(self):
        global headlines
        global rgbFileName
        global video_player
        if video_player:
            name, extension = os.path.splitext(rgbFileName)
            csvFileName = rgbFileName.replace(extension,"_video.csv")
            with open(csvFileName, 'w') as file:
                csv_writer = csv.writer(file, delimiter='\t')
                csv_writer.writerow(headlines)
                for i in xrange(0, len(self.videobox)):
                    box = self.videobox[i]
                    if len(box.box_id) > 0:
                        for j in xrange(0, len(box.box_id)):
                            master = []
                            append = master.append
                            if box.box_id[j] != -1:
                                append(box.timestamp)
                                append(box.box_id[j])
                                for param in box.box_Param[j][::]:
                                    append(param)
                                for param in box.features[j][::]:
                                    append(param)
                                append(box.annotation[j])    
                                
                                csv_writer.writerow(master)
                            else:
                                csv_writer.writerow([box.timestamp])
                    else:
						csv_writer.writerow([box.timestamp])
                    
                print ("Video csv written at: ", csvFileName) 
                
    def errorMessages(self, index):
        msgBox = QMessageBox()
        msgBox.setIcon(msgBox.Warning)
        if index == 0:
            msgBox.setWindowTitle("Open rosbag")
            msgBox.setText("Could not open rosbag")
        elif index == 1:
            msgBox.setWindowTitle("Open CSV")
            msgBox.setText("Could not process CSV file")
        elif index == 2:
            msgBox.setWindowTitle("Open rosbag")
            msgBox.setIcon(msgBox.Critical)
            msgBox.setText("Could not write video")
        elif index == 3:
            msgBox.setText("Error: Json file path error")
        elif index == 4:
            msgBox.setText("Not integer type")
        elif index == 5:
            msgBox.setText("Box id already given")
        elif index == 6:
            msgBox.setWindowTitle("Open rosbag")
            msgBox.setText("Incorrect Audio Topic")
        elif index == 8:
            msgBox.setWindowTitle("Open rosbag")
            msgBox.setText("Incorrect RGB Topic")
        elif index == 10:
            msgBox.setWindowTitle("Open CSV")
            msgBox.setText("You must select a rosbag first")

        msgBox.resize(100,40)
        msgBox.exec_()

    def play(self):
        global frameCounter
        global audio_player
        global video_player
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.videoPosition()
            self.mediaPlayer.pause()
            if audio_player:
                self.audioPlay()
            self.time_ = self.positionSlider
        else:
            self.time_ = self.mediaPlayer.position()
            if audio_player:
                self.player.setPosition(self.time_)
                self.end = audioGlobals.duration*1000 - 10
                self.audioPlay()
            if video_player:
                self.mediaPlayer.play()

        # >> Get slider position for bound box
        posSlider = self.positionSlider.value()
        #self.tickLabel.setAlignment(posSlider)
        frameCounter = int(round((self.message_count * posSlider)/(self.duration * 1000)))


    def mediaStateChanged(self, state):
        if state == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        time = "{0:.2f}".format(float(position)/1000)
        self.positionSlider.setValue(position)
        self.positionSlider.setToolTip(str(time) + ' sec')
        self.timelabel.setText(self.label_tmp.format('Time: ' + str(time) + '/ ' + str("{0:.2f}".format(self.duration)) + ' sec'))
        
        if audioGlobals.duration > 0 and self.mediaPlayer.state() != 0:
            audioGlobals.fig.drawNew(time)
            audioGlobals.fig.draw()

    def keyPressEvent(self,event):
        if event.key() == Qt.Key_Control:
            self.controlEnabled = True

    def keyReleaseEvent(self,event):
        if event.key() == Qt.Key_Control:
            self.controlEnabled = False

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

    def setPosition(self, position):
        global frameCounter
        global audio_player
        global video_player
        
        frameCounter = int(round(self.message_count * position/(self.duration * 1000)))
        if frameCounter >= self.message_count:
            frameCounter = self.message_count - 1 
        if video_player:
            self.mediaPlayer.setPosition(position)
        if audio_player:
            self.player.setPosition(position)
            
            
    def closeEvent(self, event):
        self.writeCSV()
        eA.writeCSV()
    
    def parseJson(self):
        json_basicLabel = []
        json_highLabel = []
        json_annotationColors = []
        json_eventColors = []

        with open("labels.json") as json_file:
                json_data = json.load(json_file)
                for i in json_data['basiclabels'] :
                    json_basicLabel.append(i)
                for i in json_data['highlevellabels']:
                    json_highLabel.append(i)
                for i in json_data['annotationColors'] :
                    json_annotationColors.append(i)
                for i in json_data['eventColors']:
                    json_eventColors.append(i)
        return json_basicLabel,json_highLabel, json_annotationColors, json_eventColors
Ejemplo n.º 7
0
class VoiceWindow(QMainWindow):
    switch_window1 = QtCore.pyqtSignal()
    switch_window2 = QtCore.pyqtSignal()  
    switch_openWindow = QtCore.pyqtSignal()  # class constructor
    def __init__(self):
        # call QWidget constructor
        super().__init__()
        self.ui = Ui_VoiceWindow()
        self.ui.setupUi(self)
        self.mic = []
        p1 = pyaudio.PyAudio()
        info = p1.get_host_api_info_by_index(0)
        numdevices = info.get('deviceCount')
        self.ui.DeviceBox.setDuplicatesEnabled(False)
        for i in range(0, numdevices):
            self.mic.append(p1.get_device_info_by_host_api_device_index(0, i).get('name'))
            self.ui.DeviceBox.addItem(p1.get_device_info_by_host_api_device_index(0, i).get('name'))
        p1.terminate()
        self.ID=""
        self.CHUNK = 512
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 1
        self.RATE = 16000
        self.RECORD_SECONDS = 3
        self.player = QMediaPlayer()
        self.count = 0
        self.volume = 0
        self.player.setVolume(100)
        self.ui.record1_cb.setEnabled(False)
        self.ui.record2_cb.setEnabled(False)
        self.ui.record3_cb.setEnabled(False)
        self.ui.volume_sl.setMaximum(100)
        self.ui.volume_sl.setPageStep(1)
        self.ui.volume_sl.setValue(100)
        self.ui.play_bt.setEnabled(False)
        self.ui.done_bt.setEnabled(False)
        # Disable Save in menubar until process done
        self.ui.save_act.setEnabled(False)
    

        self.ui.record_sl.setRange(0,0)
        self.ui.record_sl.sliderMoved.connect(self.set_position)

        self.player.positionChanged.connect(self.position_changed)
        self.player.durationChanged.connect(self.duration_changed)
    
        # create a timer
        self.timer = QTimer()
        # set timer timeout callback function
        self.timer.timeout.connect(self.recordHandler)
        self.timer.start(20)
        # set control_bt callback clicked  function

        self.ui.record_bt.clicked.connect(lambda: self.setCount(5))

        self.ui.volume_sl.valueChanged.connect(self.changeVolume)
        self.ui.play_bt.clicked.connect(self.playing)
        self.ui.previous_bt.clicked.connect(self.pushbutton_handler1)
        self.ui.done_bt.clicked.connect(self.pushbutton_handler2)
        # Open file menu and click New (Ctrl + N)
        self.ui.new_act.triggered.connect(self.setNew)
        # Open file menu and click Open (Ctrl + O)
        self.ui.open_act.triggered.connect(self.openUser)
        # Open file menu and click Save (Ctrl + S)
        self.ui.save_act.triggered.connect(self.saveUser)
        # Open file menu and click Exit (Ctrl + Esc)
        self.ui.exit_act.triggered.connect(self.closeApp)

    def pushbutton_handler1(self):
        self.switch_window1.emit()

    def pushbutton_handler2(self):
        with open('data/ID.txt', 'w') as f:
            f.write("")
        self.switch_window2.emit()

    def position_changed(self, position):
        self.ui.record_sl.setValue(position)
 
    def duration_changed(self, duration):
        self.ui.record_sl.setRange(0, duration)

    def set_position(self, position):
        self.player.setPosition(position)


    def setCount(self, item):
        self.count = item
        self.data_encode = []
        self.ui.record1_cb.setChecked(False)
        self.ui.record2_cb.setChecked(False)
        self.ui.record3_cb.setChecked(False)

    def setCountPlay(self, item):
        self.countPlay = item

    def changeVolume(self, value):
        self.player.setVolume(value)

    def playing(self):
        sound1 = AudioSegment.from_wav(f"data/{self.ID}/voice/1.wav")
        sound2 = AudioSegment.from_wav(f"data/{self.ID}/voice/2.wav")
        sound3 = AudioSegment.from_wav(f"data/{self.ID}/voice/3.wav")

        combined_sounds = sound1 + sound2 + sound3
        combined_sounds.export(f"data/{self.ID}/voice/joinedFile.wav", format="wav")
        filename = os.path.abspath(f"data/{self.ID}/voice/joinedFile.wav")
        self.player.setMedia(QMediaContent(QUrl.fromLocalFile(filename)))
        self.player.play()


    # handle the record
    def recordHandler(self):
        mic1 = []
        p1 = pyaudio.PyAudio()
        info = p1.get_host_api_info_by_index(0)
        numdevices = info.get('deviceCount')
        self.ui.DeviceBox.setDuplicatesEnabled(False)
        for i in range(0, numdevices):
            mic1.append(p1.get_device_info_by_host_api_device_index(0, i).get('name'))
        if mic1 != self.mic:
            print(True)
            self.ui.DeviceBox.clear()
            self.ui.DeviceBox.addItems(mic1)
            self.mic = mic1
        p1.terminate()
        print(self.ui.DeviceBox.currentIndex())
        with open(f'data/ID.txt', 'r') as f:
            self.ID = f.read()
        # If process done, save in menubar will be enabled
        if os.path.exists(f'data/{self.ID}/voice/3.wav'):
            self.ui.save_act.setEnabled(True)
        else:
            self.ui.save_act.setEnabled(False) # else it still be disabled

        # Check 3 wav files exist or not
        if os.path.exists(f'data/{self.ID}/voice/1.wav'):
            self.ui.record1_cb.setChecked(True)
        else:
            self.ui.record1_cb.setChecked(False)
        if os.path.exists(f'data/{self.ID}/voice/2.wav'):
            self.ui.record2_cb.setChecked(True)
        else:
            self.ui.record2_cb.setChecked(False)
        if os.path.exists(f'data/{self.ID}/voice/3.wav'):
            self.ui.record3_cb.setChecked(True)
            self.ui.play_bt.setEnabled(True)
            self.ui.done_bt.setEnabled(True)
        else:
            self.ui.record3_cb.setChecked(False)
            self.ui.play_bt.setEnabled(False)
            self.ui.done_bt.setEnabled(False)
        
        # Record voice 
        if (self.count>0) & (self.count<=4):
            p = pyaudio.PyAudio()

            stream = p.open(format=self.FORMAT,
                            channels=self.CHANNELS,
                            rate=self.RATE,
                            input=True,
                            frames_per_buffer=self.CHUNK,
                            input_device_index=self.ui.DeviceBox.currentIndex())

            self.ui.status_lb.setText(f"Status: * recording {5-self.count}")
            # 1 record turn will not be used 
            if (self.count!= 4):
                wave_output_filename = f"data/{self.ID}/voice/{4-self.count}.wav"
                frames = []

                # Check the record check box
                if self.count == 1:
                    self.ui.record3_cb.setChecked(True)
                    self.ui.play_bt.setEnabled(True)
                    self.ui.done_bt.setEnabled(True)
                if self.count == 2:
                    self.ui.record2_cb.setChecked(True)
                if self.count == 3:
                    self.ui.record1_cb.setChecked(True)
                for i in range(0, int(self.RATE / self.CHUNK * self.RECORD_SECONDS)):
                    data = stream.read(self.CHUNK)
                    frames.append(data)
                
                stream.stop_stream()
                stream.close()
                p.terminate()
                buff = BytesIO()
                wf = wave.open(wave_output_filename, 'wb')
                wf.setnchannels(self.CHANNELS)
                wf.setsampwidth(p.get_sample_size(self.FORMAT))
                wf.setframerate(self.RATE)
                wf.writeframes(b''.join(frames))
                wf.close()
                encoded_data = resemblyzer.preprocess_wav(wave_output_filename)
                self.data_encode.append(encoded_data)

                # Save pickle file
                with open(f'data/{self.ID}/voice/{self.ID}_encoded_wav.pickle', 'wb') as handle:
                    pickle.dump(self.data_encode, handle, protocol=pickle.HIGHEST_PROTOCOL)
            self.count -= 1
        if self.count == 0:
            # Status of not recording
            self.ui.status_lb.setText("Status: Click record")

        if self.count == 5:
            # Status of begin recording
            self.ui.status_lb.setText(f"Status: * Ready")
            self.count -= 1


# Function of menubar

    def setNew(self):
        # Pop up message box when exit. 2 option yes or no
        reply = QMessageBox.question(self,'Message','Press Yes to create New user.',QMessageBox.Yes|QMessageBox.No,QMessageBox.Yes)
        
        if reply == QMessageBox.Yes:
            # When face data and voice data have not done, 
            # click yes will lead to remove current ID folder
            with open('data/ID.txt', 'r') as f:
                ID = f.read()
            if not os.path.exists(f'data/{ID}/voice/3.wav'):
                shutil.rmtree(f'data/{ID}', ignore_errors=True)
            # Clear temporary ID
            with open('data/ID.txt', 'w') as f:
                f.write("")
            # Go to first window 
            self.switch_window2.emit()
        if reply == QMessageBox.No:
            return

    def openUser(self):
        # Go to open window 
        self.switch_openWindow.emit()

    def saveUser(self):
        # Pop up message box when exit. 2 option yes or no
        reply = QMessageBox.question(self,'Message','Press Yes to save user.',QMessageBox.Yes|QMessageBox.No,QMessageBox.Yes)
        
        if reply == QMessageBox.Yes:
            with open('data/ID.txt', 'r') as f:
                ID = f.read()
            # Clear temporary ID
            with open('data/ID.txt', 'w') as f:
                f.write("")
            self.switch_window2.emit()
        if reply == QMessageBox.No:
            return

    def closeApp(self):
        reply = QMessageBox.question(self,'Message','Press Yes to Close.',QMessageBox.Yes|QMessageBox.No,QMessageBox.Yes)
        
        if reply == QMessageBox.Yes:
            # When face data and voice data have not done, 
            # click yes will lead to remove current ID folder
            with open('data/ID.txt', 'r') as f:
                ID = f.read()
            if ID != "":
                if not os.path.exists(f'data/{ID}/voice/3.wav'):
                    print(ID)
                    shutil.rmtree(f'data/{ID}', ignore_errors=True)
            sys.exit()
        if reply == QMessageBox.No:
            return
Ejemplo n.º 8
0
class AudioPlayer(QObject):

    songPositionChanged = pyqtSignal(int)
    songDurationChanged = pyqtSignal(int)
    stateChanged = pyqtSignal(int)
    playlistChanged = pyqtSignal(QMediaPlaylist, int)

    currentSongChanged = pyqtSignal(str, str, bytes)
    currentSelectionChanged = pyqtSignal(UUID, int)

    customPlaylistCreated = pyqtSignal(UUID, str)
    libraryPlaylistCreated = pyqtSignal(UUID)

    addedToLibraryPlaylist = pyqtSignal(UUID, list)
    addedToCustomPlaylist = pyqtSignal(UUID, list)

    updatedLibraryPlaylist = pyqtSignal(UUID, list)

    playlistRemoved = pyqtSignal(UUID)

    def __init__(self, volumeLevel=40, playbackMode=QMediaPlaylist.Sequential,
                 parent=None):
        super(AudioPlayer, self).__init__(parent)

        self.__player = QMediaPlayer()
        self.__player.setVolume(volumeLevel)

        self.__player.currentMediaChanged.connect(self._onMediaChanged)
        self.__player.stateChanged.connect(
            lambda state: self.stateChanged.emit(int(state)))
        self.__player.positionChanged.connect(
            lambda x: self.songPositionChanged.emit(x))
        self.__player.durationChanged.connect(
            lambda x: self.songDurationChanged.emit(x))

        self.__playlistManager = PlaylistManger()

        self.__playlistManager.customPlaylistCreated.connect(
            lambda uuid, name: self.customPlaylistCreated.emit(uuid, name))
        self.__playlistManager.libraryPlaylistCreated.connect(
            lambda p: self.libraryPlaylistCreated.emit(p))
        
        self.__playlistManager.currentPlaylistChanged.connect(
            self._onChangedPlaylist)
        self.__playlistManager.currentPlaylistChanged.connect(
            lambda p, i: self.playlistChanged.emit(p, i))

        self.__playlistManager.playlistRemoved.connect(
            lambda uuid: self.playlistRemoved.emit(uuid))

        self.__playlistManager.addedToLibraryPlaylist.connect(
            lambda uuid, l: self.addedToLibraryPlaylist.emit(uuid, l))
        self.__playlistManager.addedToCustomPlaylist.connect(
            lambda uuid, l: self.addedToCustomPlaylist.emit(uuid, l))

        self.__playlistManager.updatedLibraryPlaylist.connect(
            lambda uuid, l: self.updatedLibraryPlaylist.emit(uuid, l))

    def createCustomPlaylist(self, name=None, urls=None):
        self.__playlistManager.createCustomPlaylist(name, urls)

    def createLibraryPlaylist(self, urls=None):
        self.__playlistManager.createLibraryPlaylist(urls)

    def addToLibraryPlaylist(self, url=None):
        self.__playlistManager.addToLibraryPlaylist(url)

    def updateLibraryPlaylist(self, url=None):
        self.__playlistManager.updateLibraryPlaylist(url)

    def renamePlaylist(self, uuid, newName):
        self.__playlistManager.renamePlaylist(uuid, newName)

    def addSongsToCustomPlaylist(self, uuid, urls=[]):
        self.__playlistManager.addSongsToCustomPlaylist(uuid, urls)

    def removeSong(self, uuid, row):
        self.__playlistManager.removeSong(uuid, row)

    def setPlaylist(self, uuid, index=0):
        if (self.__player.playlist() and
                self.__playlistManager.isCurrentPlaylist(uuid)):
            if index == self.__player.playlist().currentIndex():
                if self.__player.state() == QMediaPlayer.PlayingState:
                    self.__player.pause()
                else:
                    self.__player.play()
            else:
                self.__player.playlist().setCurrentIndex(index)
        else:
            self.__playlistManager.setPlaylist(uuid, index)

    def hasLibraryPlaylist(self):
        return self.__playlistManager.hasLibraryPlaylist()

    def removePlaylist(self, uuid):
        self.__playlistManager.removePlaylist(uuid)

    def getCurrentPlaylist(self):
        self.__playlistManager.getCurrentPlaylist()

    def getCurrentQMediaPlaylist(self):
        self.__player.playlist()

    def isPlayerAvailable(self):
        return self.__player.isAvailable()

    def getDuration(self):
        return self.__player.duration()

    def getPlayer(self):
        return self.__player

    def getState(self):
        return self.__player.state()

    def play(self):
        if self.__player.playlist():
            self.__player.play()

    def pause(self):
        if self.__player.playlist():
            self.__player.pause()

    def stop(self):
        if self.__player.playlist():
            self.__player.stop()

    def previousEnhanced(self, sameSongMillis):
        if self.__player.position() <= sameSongMillis:
            self.previous()
        else:
            self.__player.setPosition(0)

    def previous(self):
        if self.__player.playlist():
            self.__player.playlist().previous()

    def next(self):
        if self.__player.playlist():
            self.__player.playlist().next()

    def setVolume(self, value):
        self.__player.setVolume(value)

    def setPosition(self, milliseconds):
        self.__player.setPosition(milliseconds)

    def playlistCurrentIndex(self):
        if self.__player.playlist():
            return self.__player.playlist().currentIndex()

    def setCurrentPlaylistIndex(self, index):
        if self.__player.playlist():
            self.__player.playlist().setCurrentIndex(index)

    def _onChangedPlaylist(self, playlist, index, playIt=False):
        self.__player.setPlaylist(playlist)
        if playlist:
            playlist.setCurrentIndex(index)
        if playIt:
            self.play()

    def _onMediaChanged(self, media):
        if media.isNull() and self.__player.playlist():
            self.__player.playlist().setCurrentIndex(0)
            media = self.__player.playlist().media(0)
        if media.isNull():
            return

        title, artist, cover = self.__playlistManager.getBasicSongInfo(media)

        self.currentSongChanged.emit(title, artist, cover)

        uuid = self.__playlistManager.getCurrentPlaylistUuid()
        index = self.__playlistManager.getCurrentSongIndex()
        self.currentSelectionChanged.emit(uuid, index)

    # def saveSettings(self):
    #     # settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
    #     #                      QCoreApplication.organizationName(),
    #     #                      QCoreApplication.applicationName())

    #     # settings.beginGroup("music_player")

    #     # # if self.__playlistManager.getLibraryPlaylist():
    #     # #     libraryDirectories = self.__playlistManager.getLibraryPlaylist().getDirectories()
    #     # #     settings.beginWriteArray('library_playlist',
    #     # #                              len(libraryDirectories))
    #     # #     for index, value in enumerate(libraryDirectories):
    #     # #         settings.setArrayIndex(index)
    #     # #         settings.setValue("url", value)
    #     # #     settings.endArray()

    #     # customPlaylists = self.__playlistManager.getCustomPlaylists()
    #     # settings.beginWriteArray('custom_playlists',
    #     #                          len(customPlaylists))
    #     # for index, value in enumerate(customPlaylists):
    #     #     settings.setArrayIndex(index)
    #     #     playlistName = settings.value('name', value.getName())
    #     #     playlistUrls = value.getAddedSongUrls()
    #     #     settings.beginWriteArray(playlistName,
    #     #                              len(playlistUrls))
    #     #     for i, v in enumerate(playlistUrls):
    #     #         settings.setArrayIndex(i)
    #     #         settings.setValue("url", v)
    #     #     settings.endArray()
    #     # settings.endArray()

    #     # settings.endGroup()
    #     # if self.__playlistManager.getLibraryPlaylist():
    #     #     libraryDirectories = self.__playlistManager.getLibraryPlaylist().getDirectories()
    #     #     settings.beginWriteArray('library_playlist',
    #     #                              len(libraryDirectories))
    #     #     for index, value in enumerate(libraryDirectories):
    #     #         settings.setArrayIndex(index)
    #     #         settings.setValue("url", value)
    #     #     settings.endArray()

    #     customPlaylists = self.__playlistManager.getCustomPlaylists()
    #     for playlist in customPlaylists:
    #         playlistName = playlist.getName()
    #         for url in playlist:
    #             pass

    # def restoreSettings(self):
    #     settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
    #                          QCoreApplication.organizationName(),
    #                          QCoreApplication.applicationName())

    #     settings.beginGroup("music_player")

    #     # size = settings.beginReadArray('library_playlist')
    #     # libraryDirectories = []
    #     # for i in range(size):
    #     #     settings.setArrayIndex(i)
    #     #     libraryDirectories.append(settings.value("url"))
    #     # settings.endArray()

    #     customPlaylists = {}
    #     size = settings.beginReadArray('custom_playlists')
    #     for i in range(size):
    #         urls = []
    #         settings.setArrayIndex(i)
    #         playlistName = settings.value('name')
    #         print(playlistName)
    #         size2 = settings.beginReadArray(playlistName)
    #         for j in range(size2):
    #             settings.setArrayIndex(j)
    #             url = settings.value("url")
    #             urls.append(url)
    #         settings.endArray()
    #         customPlaylists[playlistName] = urls
    #     settings.endArray()

    #     settings.endGroup()

    #     print('-------')
    #     print(customPlaylists)





        # settings = QSettings(QCoreApplication.organizationName(),
        #                      QCoreApplication.applicationName())
        # settings.beginGroup("music_player")

        # size = settings.beginReadArray('library_playlist')
        # if not size == 0:
        #     for i in range(0, size):
        #         settings.setArrayIndex(i)
        #         url = settings.value("url")
        # settings.endArray()

        # if url:
        #     from audio.playlist_models import DirectoryPlaylist

        #     playlist = DirectoryPlaylist()
        #     playlist.add_directory(url)
        #     self.addAndSetPlaylist(playlist, 2)

        # settings.endGroup()
        pass
class App(QMainWindow):

    def __init__(self, song):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.title = 'PyTunes'
        self.left = 300
        self.top = 300
        self.width = 300
        self.height = 150
        self.color = 0  # 0- toggle to dark 1- toggle to light
        self.userAction = -1  # 0- stopped, 1- playing 2-paused
        self.initUI()
        self.song = song

    def initUI(self):
        # Add file menu

        self.addControls()

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.toggleColors()
        self.show()

    def addControls(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)
        # Add song controls
        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(100)
        playBtn = QPushButton('Play')  # play button
        pauseBtn = QPushButton('Pause')  # pause button
        # Add button layouts
        controlArea = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()
        # Add buttons to song controls layout
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        # Add buttons to playlist controls layout
        # Add to vertical layout
        controlArea.addWidget(volumeslider)
        controlArea.addLayout(controls)
        controlArea.addLayout(playlistCtrlLayout)
        wid.setLayout(controlArea)
        # Connect each signal to their appropriate function
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)

        self.statusBar()
        self.playlist.currentMediaChanged.connect(self.songChanged)

    def openFile(self):
        song = QFileDialog.getOpenFileName(self, "Open Song", "~", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")
        print(song)

        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
            else:
                self.playlist.addMedia(QMediaContent(url))

    def addFiles(self):
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            self.userAction = 1
    
    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, 'Open Music Folder', '~')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
    
    def playhandler(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.play()
            self.userAction = 1

    def pausehandler(self):
        self.userAction = 2
        self.player.pause()

    def changeVolume(self, value):
        self.player.setVolume(value)
    
    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            self.statusBar().showMessage(url.fileName())

    def toggleColors(self):
        """ Fusion dark palette from https://gist.github.com/QuantumCD/6245215. Modified by me and J.J. """
        app.setStyle("Fusion")
        palette = QPalette()
        if self.color == 0:
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(25, 25, 25))
            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.Link, QColor(235, 101, 54))
            palette.setColor(QPalette.Highlight, QColor(235, 101, 54))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 1
        elif self.color == 1:
            palette.setColor(QPalette.Window, Qt.white)
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, QColor(240, 240, 240))
            palette.setColor(QPalette.AlternateBase, Qt.white)
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, Qt.white)
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(66, 155, 248))
            palette.setColor(QPalette.Highlight, QColor(66, 155, 248))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 0
Ejemplo n.º 10
0
class Window(QtWidgets.QDialog):

    def __init__(self):
        super().__init__()
        self.setGeometry(50, 50, 300, 400)
        self.setWindowTitle("Rolev Player")

# LIBRARY ROOT DIR FOLDER
        self.search_label = QtWidgets.QLabel("Select a music folder:", self)
        self.search_label.setGeometry(10, 5, 205, 10)

        self.btn_root_folder = QtWidgets.QPushButton("Browse", self)
        self.btn_root_folder.setGeometry(215, 20, 75, 25)

        # the text field of the currently selected root directory
        self.dir_text_field = QtWidgets.QLineEdit(self)
        self.dir_text_field.setGeometry(10, 20, 200, 25)

        self.btn_root_folder.clicked.connect(self.on_btn_root_folder)

# CURRENT MEDIA LABEL
        self.current_media_label = QtWidgets.QLabel("Now Playing: ", self)
        self.current_media_label.setGeometry(10, 260, 250, 15)

# CURRENT ALBUM COVER
        self.current_album_cover = QtWidgets.QLabel("Image", self)
        self.current_album_cover.setGeometry(10, 180, 75, 75)
        self.current_album_cover.setScaledContents(True)

# ARTIST DROP BOX
        self.artist_select_label = QtWidgets.QLabel("Artist", self)
        self.artist_select_label.setGeometry(10, 50, 250, 25)

        self.artist_select = QtWidgets.QComboBox(self)
        self.artist_select.setGeometry(10, 70, 250, 25)
        self.artist_select.activated[str].connect(self.on_artist_selection)

# ALBUMS DROP BOX
        self.album_select_label = QtWidgets.QLabel("Albums", self)
        self.album_select_label.setGeometry(10, 90, 250, 25)

        self.album_select = QtWidgets.QComboBox(self)
        self.album_select.setGeometry(10, 110, 250, 25)
        self.album_select.activated[str].connect(self.on_album_selection)

# SONGS DROP BOX
        self.song_select_label = QtWidgets.QLabel("Current Playlist", self)
        self.song_select_label.setGeometry(10, 130, 250, 25)

        self.song_select = QtWidgets.QComboBox(self)
        self.song_select.setGeometry(10, 150, 250, 25)
        self.song_select.activated[str].connect(self.on_song_selection)

# PLAYLIST
        self.playlist = QMediaPlaylist()
        self.playlist.currentIndexChanged.connect(self.meta_data_changed)

# MEDIA PLAYER
        self.player = QMediaPlayer()
        self.player.setPlaylist(self.playlist)
        self.player.playlist().setPlaybackMode(QMediaPlaylist.Loop)
        self.player.setVolume(50)

        self.player.durationChanged.connect(self.on_dur_change)
        self.player.positionChanged.connect(self.on_pos_change)

# VOLUME SLIDER
        self.slider_volume_label = QtWidgets.QLabel("Volume", self)
        self.slider_volume_label.setGeometry(10, 345, 50, 25)

        self.slider_volume = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.slider_volume.setGeometry(60, 350, 130, 20)
        self.slider_volume.setRange(0, 100)
        self.slider_volume.setValue(50)
        self.slider_volume.valueChanged.connect(self.volume_change)

# PROGRESS SLIDER
        self.slider_progress_label = QtWidgets.QLabel("Progress", self)
        self.slider_progress_label.setGeometry(10, 315, 50, 25)

        self.slider_progress = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.slider_progress.setGeometry(60, 320, 130, 20)
        self.slider_progress.sliderMoved.connect(self.progress_change)

# LYRICS SEARCH
        self.btn_lyrics = QtWidgets.QPushButton("Search\n Lyrics", self)
        self.btn_lyrics.setGeometry(220, 310, 70, 80)
        self.btn_lyrics.clicked.connect(self.on_lyrics)

# ALBUM INFO SEARCH
        self.btn_album_info = QtWidgets.QPushButton(
            "Search\nAlbum\nInfo", self)
        self.btn_album_info.setGeometry(105, 180, 75, 75)
        self.btn_album_info.clicked.connect(self.on_album_info)

# ARTIST INFO SEARCH
        self.btn_artist_info = QtWidgets.QPushButton(
            "Search\nArtist\nInfo", self)
        self.btn_artist_info.setGeometry(200, 180, 75, 75)
        self.btn_artist_info.clicked.connect(self.on_artist_info)

# PREV SONG BUTTON
        self.btn_prev = QtWidgets.QPushButton("Prev", self)
        self.btn_prev.setGeometry(10, 280, 75, 25)
        self.btn_prev.clicked.connect(self.on_btn_prev)

# NEXT SONG BUTTON
        self.btn_next = QtWidgets.QPushButton("Next", self)
        self.btn_next.setGeometry(200, 280, 75, 25)
        self.btn_next.clicked.connect(self.on_btn_next)

# PLAY/PAUSE BUTTON
        self.btn_play_pause = QtWidgets.QPushButton("Play", self)
        self.btn_play_pause.setGeometry(105, 280, 75, 30)
        self.btn_play_pause.clicked.connect(self.on_btn_play_pause)

        self.show()

    def on_btn_root_folder(self):
        self.root_dir = QtWidgets.QFileDialog().getExistingDirectory()
        self.dir_text_field.setText(self.root_dir)
        self.library = LibraryLoader.load_music_from_dir(
            self.dir_text_field.text())

        self.artist_select.clear()
        self.album_select.clear()
        self.song_select.clear()
        self.playlist.clear()

        self.btn_play_pause.setText("Play")
        self.artist_select.addItem("All Artists")
        for artist in self.library:
            self.artist_select.addItem(artist)
            for album in self.library[artist]:
                self.album_select.addItem(album)
        self.load_all_songs()

    def on_artist_selection(self):
        current_artist = self.artist_select.currentText()

        self.album_select.clear()
        self.song_select.clear()
        self.playlist.clear()

        self.btn_play_pause.setText("Play")
        self.album_select.addItem("All Albums")
        if current_artist == "All Artists":
            for artist in self.library:
                for album in self.library[artist]:
                    self.album_select.addItem(album)
            self.load_all_songs()
        else:
            for album in self.library[current_artist]:
                self.album_select.addItem(album)
            self.load_all_from_artist(current_artist)

    def load_all_songs(self):
        for artist in self.library:
            for album in self.library[artist]:
                for song in self.library[artist][album]:
                    self.song_select.addItem(song[0])
                    self.playlist.addMedia(
                        QMediaContent(QtCore.QUrl.fromLocalFile(song[1])))

    def load_all_from_artist(self, artist):
        for album in self.library[artist]:
            for song in self.library[artist][album]:
                self.song_select.addItem(song[0])
                self.playlist.addMedia(
                    QMediaContent(QtCore.QUrl.fromLocalFile(song[1])))

    def on_album_selection(self):
        current_artist = self.artist_select.currentText()
        current_album = self.album_select.currentText()
        self.song_select.clear()
        self.playlist.clear()
        self.btn_play_pause.setText("Play")
        if current_album == "All Albums" and current_artist == "All Artists":
            self.load_all_songs()

        elif current_album == "All Albums":
            self.load_all_from_artist(current_artist)

        elif current_artist == "All Artists":
            for artist in self.library:
                for album in self.library[artist]:
                    if album == self.album_select.currentText():
                        for song in self.library[artist][album]:
                            self.song_select.addItem(song[0])
                            self.playlist.addMedia(
                                QMediaContent(
                                    QtCore.QUrl.fromLocalFile(song[1])))
        else:
            for song in self.library[current_artist][current_album]:
                self.song_select.addItem(song[0])
                self.playlist.addMedia(
                    QMediaContent(QtCore.QUrl.fromLocalFile(song[1])))

    def on_song_selection(self):
        index = self.song_select.currentIndex()
        self.playlist.setCurrentIndex(index)

# GETTING THE CURRENT SONG METADATA
    # Returns a SONG OBJECT and not the current song title
    # For the title of the currently playing song use get_current_title()
    def get_current_song(self):
        curr_url = self.playlist.currentMedia().canonicalUrl().toString()[8:]
        if curr_url:
            return LibraryLoader.create_song(curr_url)

    def get_current_artist(self):
        if self.get_current_song() is not None:
            return self.get_current_song().artist

    def get_current_album(self):
        if self.get_current_song() is not None:
            return self.get_current_song().album

    def get_current_path(self):
        if self.get_current_song() is not None:
            return self.get_current_song().path

    def get_current_album_path(self):
        if self.get_current_path() is not None:
            return self.get_current_path().rsplit("/", 1)[0]

    def get_current_title(self):
        if self.get_current_song() is not None:
            return self.get_current_song().name

    def on_lyrics(self):
        if self.get_current_song() is not None:
            curr_artist = self.get_current_artist()
            curr_song = self.get_current_title()

            found_lyrics = RequestLyrics.search_song_lyrics(
                curr_artist, curr_song)
            choice = QtWidgets.QMessageBox.question(
                self, "Lyrics", found_lyrics[0],
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
            if choice == QtWidgets.QMessageBox.Yes:
                webbrowser.open(found_lyrics[1])
        else:
            QtWidgets.QMessageBox.information(
                self, "Lyrics", "No lyrics found or no media is loaded!")

    def on_album_info(self):
        album = self.get_current_album()
        artist = self.get_current_artist()
        if (album is None) or (artist is None):
            print("Please, load a song first!")
        else:
            artist_info, album_info = AlbumArtwork.album_artist_info(
                artist, album)
            if album_info is not None:
                webbrowser.open(album_info)

    def on_artist_info(self):
        album = self.get_current_album()
        artist = self.get_current_artist()
        if (album is None) or (artist is None):
            print("Please, load a song first!")
        else:
            artist_info, album_info = AlbumArtwork.album_artist_info(
                artist, album)
            if artist_info is not None:
                webbrowser.open(artist_info)

    def on_btn_play_pause(self):
        if self.player.state() in (0, 2):
            self.player.play()
            if self.player.state() == 1:
                self.btn_play_pause.setText("Pause")
        else:
            self.player.pause()
            self.btn_play_pause.setText("Play")

    def on_btn_next(self):
        self.player.playlist().next()

    def on_btn_prev(self):
        self.player.playlist().previous()

    def on_dur_change(self, length):
        self.slider_progress.setMaximum(length)

    def on_pos_change(self, position):
        self.slider_progress.setValue(position)

    def volume_change(self):
        volume = self.slider_volume.value()
        self.player.setVolume(volume)

    def progress_change(self):
        position = self.slider_progress.value()
        self.player.setPosition(position)

    def meta_data_changed(self):

        now_playing = self.get_current_title()
        self.current_media_label.setText("Now Playing: " + now_playing)

        # Updating the currently playing album cover
        curr_album_path = self.get_current_album_path()
        curr_album = self.get_current_album()
        curr_artist = self.get_current_artist()
        cover_url = AlbumArtwork.album_cover(
            curr_album_path, curr_artist, curr_album)

        self.current_album_cover.setPixmap(QPixmap(cover_url))
        Scrobbler.scrobble(self.get_current_artist(), self.get_current_title())
Ejemplo n.º 11
0
class PlaybackPanel(SpecialLabel):
    desktop_lyric_state_changed_signal = pyqtSignal(bool)
    playmode_changed_signal = pyqtSignal(int, int)
    media_player_notify_signal = pyqtSignal(int)
    muted_changed_signal = pyqtSignal(int)
    mark_favorite_completed_signal = pyqtSignal()
    current_media_changed_signal = pyqtSignal()
    music_ended_signal = pyqtSignal()
    update_window_lyric_signal = pyqtSignal(str, str)
    show_artist_info_signal = pyqtSignal(str)
    dont_hide_main_window_signal = pyqtSignal()

    def __init__(self, parent=None):
        super(PlaybackPanel, self).__init__(parent)
        self.initial_mediaplayer()
        self.create_actions()
        self.setup_ui()
        self.create_connections()
        self.initial_params()

    def create_connections(self):
        self.artistHeadLabel.clicked.connect(self.show_artist_info)
        self.desktopLyric.hide_desktop_lyric_signal.connect(self.desktop_lyric_closed)
        self.seekSlider.valueChanged.connect(self.slider_value_changed)
        self.seekSlider.sliderPressed.connect(self.slider_pressed)
        self.seekSlider.sliderReleased.connect(self.seek)
        self.mediaPlayer.positionChanged.connect(self.tick)
        self.mediaPlayer.mutedChanged.connect(self.muted_changed_signal.emit)
        self.mediaPlayer.stateChanged.connect(self.state_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)
        self.mediaPlayer.mediaStatusChanged.connect(self.media_status_changed)
        self.mediaPlayer.currentMediaChanged.connect(self.current_media_changed)

    def initial_mediaplayer(self):
        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setNotifyInterval(500)
        self.set_volume(globalSettings.Volume)

    def initial_params(self):
        self.playlist = None
        self.artistName = "Zheng-Yejian"
        self.clickPlayFlag = False  # 用来标志一首歌是否是主动点击选中的
        self.timerFlag = False
        self.timeStart = 0
        self.timeSpan = 0
        self.sourcePath = ""
        self.errorType = Configures.NoError
        self.currentSourceRow = -1
        self.nearPlayedSongs = []
        self.downloadDir = globalSettings.DownloadfilesPath
        self.songinfosManager = SonginfosManager()
        self.totalTime = Configures.ZeroTime
        self.playmode = Configures.PlaymodeRandom  # 播放模式指示器
        playlistTemp = Playlist()
        playlistTemp.fill_list(Configures.PlaylistFavorite)
        self.lovedSongs = playlistTemp.get_titles()

    def set_playlist(self, playlist):
        self.playlist = playlist
        self.currentSourceRow = self.playlist.get_current_row()

    def create_actions(self):
        self.nextAction = QAction(QIcon(IconsHub.ControlNext), "下一首", self, enabled=True, triggered=self.next_song)

        self.playAction = QAction(QIcon(IconsHub.ControlPlay), "播放/暂停", self, enabled=True, triggered=self.play_music)

        self.previousAction = QAction(
            QIcon(IconsHub.ControlPrevious), "上一首", self, enabled=True, triggered=self.previous_song
        )

        self.stopAction = QAction(
            QIcon(IconsHub.ControlStop), "停止", self, enabled=True, triggered=self.stop_music_but_timing
        )

    def get_play_button_action(self):
        return self.playAction

    def get_previous_button_action(self):
        return self.previousAction

    def get_next_button_action(self):
        return self.nextAction

    def get_stop_button_action(self):
        return self.stopAction

    def set_download_dir(self, dir):
        self.downloadDir = dir

    def get_loved_songs(self):
        return self.lovedSongs

    def get_songinfos_manager(self):
        return self.songinfosManager

    def setup_ui(self):
        self.setFixedHeight(50)
        # 桌面歌词标签
        self.desktopLyric = desktop_lyric.DesktopLyric()
        self.desktopLyric.set_color(globalSettings.DesktoplyricColors)
        # 3个标签
        self.artistHeadLabel = LabelButton()
        self.artistHeadLabel.setToolTip(self.tr("查看歌手信息"))
        self.artistHeadLabel.setFixedSize(QSize(42, 42))
        self.artistHeadLabel.setScaledContents(True)
        self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous))

        self.musicTitleLabel = NewLabel()
        self.musicTitleLabel.setObjectName("musicTitleLabel")
        self.musicTitleLabel.setFixedSize(QSize(370, 20))
        self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER")
        self.timeLabel = QLabel("00:00/00:00")
        self.timeLabel.setObjectName("timeLabel")
        self.timeLabel.setFixedHeight(20)
        self.timeLabel.setAlignment(Qt.AlignRight and Qt.AlignVCenter)

        # 五个基本按键
        self.playmodeButton = QToolButton(clicked=self.change_playmode)
        self.playmodeButton.setFocusPolicy(Qt.NoFocus)

        self.playmodeButton.setIcon(QIcon(IconsHub.PlaymodeRandom))
        self.playmodeButton.setIconSize(QSize(25, 25))
        self.playmodeButton.setToolTip("随机播放")

        self.favoriteButton = QToolButton(clicked=self.mark_as_favorite)
        self.favoriteButton.setFocusPolicy(Qt.NoFocus)
        self.favoriteButton.setToolTip("收藏")
        self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
        self.favoriteButton.setIconSize(QSize(20, 20))

        self.previousButton = QToolButton()
        self.previousButton.setFocusPolicy(Qt.NoFocus)
        self.previousButton.setIconSize(QSize(40, 40))
        self.previousButton.setShortcut(QKeySequence("Ctrl + Left"))
        self.previousButton.setDefaultAction(self.previousAction)

        self.playButton = QToolButton()
        self.playButton.setFocusPolicy(Qt.NoFocus)
        self.playButton.setIconSize(QSize(40, 40))
        self.playButton.setShortcut(QKeySequence("Ctrl + Down"))
        self.playButton.setDefaultAction(self.playAction)

        self.nextButton = QToolButton()
        self.nextButton.setFocusPolicy(Qt.NoFocus)
        self.nextButton.setIconSize(QSize(40, 40))
        self.nextButton.setFocusPolicy(Qt.NoFocus)
        self.nextButton.setShortcut(QKeySequence("Ctrl + Right"))
        self.nextButton.setDefaultAction(self.nextAction)

        self.desktopLyricButton = QToolButton(clicked=self.show_desktop_lyric)
        self.desktopLyricButton.setToolTip(self.tr("桌面歌词"))
        self.desktopLyricButton.setFocusPolicy(Qt.NoFocus)
        self.desktopLyricButton.setIcon(QIcon(IconsHub.DesktopLyric))
        self.desktopLyricButton.setIconSize(QSize(25, 25))

        self.seekSlider = QSlider(Qt.Horizontal)
        self.seekSlider.setObjectName("seekSlider")
        self.seekSlider.setFixedHeight(20)
        self.seekSlider.setFocusPolicy(Qt.NoFocus)
        self.seekSlider.setRange(0, 0)

        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.favoriteButton)
        hbox1.addWidget(self.musicTitleLabel)
        hbox1.addStretch()
        hbox1.addWidget(self.timeLabel)
        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.setSpacing(5)
        vbox1.addWidget(self.seekSlider)

        mainLayout = QHBoxLayout(self)
        mainLayout.setContentsMargins(2, 0, 0, 0)
        mainLayout.addWidget(self.artistHeadLabel)
        mainLayout.addWidget(self.previousButton)
        mainLayout.addWidget(self.playButton)
        mainLayout.addWidget(self.nextButton)
        mainLayout.addLayout(vbox1)
        mainLayout.addWidget(self.playmodeButton)
        mainLayout.addWidget(self.desktopLyricButton)

    def show_desktop_lyric(self):
        if self.desktopLyric.isHidden():
            beToOff = True
            self.desktopLyric.show()
            self.desktopLyric.original_place()
        else:
            beToOff = False
            self.desktopLyric.hide()
        self.desktop_lyric_state_changed_signal.emit(beToOff)

    def desktop_lyric_closed(self):
        self.desktop_lyric_state_changed_signal.emit(False)

    def change_playmode(self):
        oldPlaymode = self.playmode
        if self.playmode == Configures.PlaymodeRandom:
            self.set_new_playmode(Configures.PlaymodeOrder)
        elif self.playmode == Configures.PlaymodeOrder:
            self.set_new_playmode(Configures.PlaymodeSingle)
        elif self.playmode == Configures.PlaymodeSingle:
            self.set_new_playmode(Configures.PlaymodeRandom)
        self.playmode_changed_signal.emit(oldPlaymode, self.playmode)

    def set_new_playmode(self, playmode):
        self.playmode = playmode
        if playmode == Configures.PlaymodeRandom:
            iconPath = IconsHub.PlaymodeRandom
            toolTip = Configures.PlaymodeRandomText
        elif playmode == Configures.PlaymodeOrder:
            iconPath = IconsHub.PlaymodeOrder
            toolTip = Configures.PlaymodeOrderText
        else:
            iconPath = IconsHub.PlaymodeSingle
            toolTip = Configures.PlaymodeSingleText
        self.playmodeButton.setIcon(QIcon(iconPath))
        self.playmodeButton.setToolTip(toolTip)

    def ui_initial(self):
        self.mediaPlayer.stop()
        self.totalTime = "00:00"
        self.playAction.setIcon(QIcon(IconsHub.ControlPlay))
        self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER")
        self.artistName = "Zheng-Yejian"
        self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous))
        self.seekSlider.setRange(0, 0)
        self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
        self.favoriteButton.setToolTip("收藏")
        self.timeLabel.setText("00:00/00:00")

    def set_volume(self, volume):
        self.mediaPlayer.setVolume(volume)

    def set_muted(self, muted):
        self.mediaPlayer.setMuted(muted)

    def tick(self):
        currentTime = self.mediaPlayer.position()
        self.seekSlider.setValue(currentTime)
        cTime = format_position_to_mmss(currentTime // 1000)
        self.timeLabel.setText(cTime + "/" + self.totalTime)
        self.media_player_notify_signal.emit(currentTime)

    def slider_value_changed(self, value):
        cTime = format_position_to_mmss(value // 1000)
        self.timeLabel.setText("%s/%s" % (cTime, self.totalTime))
        self.media_player_notify_signal.emit(value)

    def slider_pressed(self):
        self.mediaPlayer.positionChanged.disconnect(self.tick)

    def seek(self):
        if self.mediaPlayer.state() == QMediaPlayer.StoppedState:
            self.mediaPlayer.play()
            self.mediaPlayer.setPosition(self.seekSlider.value())
        else:
            self.mediaPlayer.setPosition(self.seekSlider.value())
            self.mediaPlayer.play()
        self.mediaPlayer.positionChanged.connect(self.tick)

    def duration_changed(self, duration):
        self.seekSlider.setMaximum(duration)
        exactTotalTime = format_position_to_mmss(self.mediaPlayer.duration() // 1000)
        self.timeLabel.setText("%s/%s" % (Configures.ZeroTime, exactTotalTime))
        if self.totalTime != exactTotalTime:
            self.totalTime = exactTotalTime
            self.playlist.set_music_time_at(self.currentSourceRow, exactTotalTime)

    def check_favorite(self):
        if self.currentSourceRow >= 0:
            if self.playlist.get_music_title_at(self.currentSourceRow) in self.lovedSongs:
                self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
                self.favoriteButton.setToolTip("取消收藏")
            else:
                self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo))
                self.favoriteButton.setToolTip("收藏")
            if self.playlist.get_name() == Configures.PlaylistFavorite:
                self.favoriteButton.setToolTip("收藏")

    def mark_as_favorite(self):
        if (
            self.playlist.get_name() == Configures.PlaylistFavorite
            or not self.playlist.length()
            or self.currentSourceRow < 0
        ):
            return
        path = self.playlist.get_music_path_at(self.currentSourceRow)
        title = self.playlist.get_music_title_at(self.currentSourceRow)
        if self.playlist.get_name() == Configures.PlaylistOnline:
            musicName = get_full_music_name_from_title(title)
            musicPath = os.path.join(self.downloadDir, musicName)
            musicPathO = os.path.join(Configures.MusicsDir, musicName)
            if not os.path.exists(musicPath) and not os.path.exists(musicPathO):
                QMessageBox.information(self, "提示", "请先下载该歌曲再添加喜欢!")
                return
            if os.path.exists(musicPath):
                path = musicPath
            else:
                path = musicPathO
        elif not os.path.exists(path):
            QMessageBox.information(self, "提示", "路径'" + "%s" % path + "'无效,无法标记喜欢!")
            return
        playlistTemp = Playlist()
        playlistTemp.fill_list(Configures.PlaylistFavorite)
        if title in self.lovedSongs:
            playlistTemp.remove_item_at(self.lovedSongs.index(title))
            playlistTemp.commit_records()
            self.lovedSongs.remove(title)
            self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo))
            self.favoriteButton.setToolTip("收藏")
        else:
            playlistTemp.add_item_from_path(path)
            playlistTemp.commit_records()
            self.lovedSongs.append(title)
            self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
            self.favoriteButton.setToolTip("取消收藏")
        self.mark_favorite_completed_signal.emit()

    def show_artist_info(self):
        if self.artistName:
            self.show_artist_info_signal.emit(self.artistName)

    def decide_to_play_or_pause(self, row):
        if row != self.currentSourceRow:
            self.set_media_source_at_row(row, clickPlayFlag=True)
        elif self.mediaPlayer.state() in (QMediaPlayer.PausedState, QMediaPlayer.StoppedState):
            self.mediaPlayer.play()
        elif self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()

    def set_media_source_at_row(self, row, clickPlayFlag=False):
        if not self.playlist.length() or row < 0:
            return
        self.stop_music()
        self.clickPlayFlag = clickPlayFlag
        self.playlist.set_current_row(row)
        sourcePath = self.playlist.get_music_path_at(row)
        self.title = self.playlist.get_music_title_at(row)
        self.sourceTrace = "local" if self.playlist.get_music_id_at(row) == Configures.LocalMusicId else "online"
        self.artistName, self.musicName = get_artist_and_musicname_from_title(self.title)
        self.playlistName = self.playlist.get_name()
        self.totalTime = self.playlist.get_music_time_at(row)
        self.album = self.playlist.get_music_album_at(row)
        self.errorType = Configures.NoError
        isAnUrl = False
        if not os.path.exists(sourcePath):
            if self.playlist.get_name() == Configures.PlaylistOnline:
                if sourcePath == Configures.NoLink:
                    musicId = self.playlist.get_music_id_at(row)
                    sourcePath = SearchOnline.get_song_link(musicId)
                    if sourcePath:
                        self.playlist.set_music_path_at(row, sourcePath)
                    else:
                        self.errorType = Configures.UrlError
                isAnUrl = True
            else:
                self.errorType = Configures.PathError
                sourcePath = "/usr/share/sounds/error_happened.ogg"
        if self.errorType == Configures.NoError:
            self.sourcePath = sourcePath
            self.musicFileName = get_base_name_from_path(sourcePath)
            self.playedDate = get_time_of_now()
            self.songinfosManager.update_datas_of_item(
                self.musicFileName,
                self.playedDate,
                self.musicName,
                self.artistName,
                self.totalTime,
                self.album,
                self.playlistName,
            )
            if not self.timerFlag:
                self.timerFlag = True
                self.timeSpan = 0
            if isAnUrl:
                url = QUrl(sourcePath)
            else:
                url = QUrl.fromLocalFile(sourcePath)
            self.play_from_url(url)
        else:
            self.timerFlag = False
            self.dont_hide_main_window_signal.emit()
            if self.errorType == Configures.DisnetError:
                QMessageBox.critical(
                    self, "错误", "联网出错!\n无法联网播放歌曲'%s'!\n您最好在网络畅通时下载该曲目!" % self.playlist.get_music_title_at(row)
                )
            elif self.errorType == Configures.PathError:
                QMessageBox.information(self, "提示", "路径'%s'无效,请尝试重新下载并添加对应歌曲!" % self.playlist.get_music_path_at(row))

    def play_from_url(self, url):
        mediaContent = QMediaContent(url)
        self.mediaPlayer.setMedia(mediaContent)
        self.mediaPlayer.play()

    def state_changed(self, newState):
        if self and newState in [QMediaPlayer.PlayingState, QMediaPlayer.PausedState, QMediaPlayer.StoppedState]:
            if not self.playlist.length():
                return
            iconPath = IconsHub.ControlPause
            if newState in [QMediaPlayer.StoppedState, QMediaPlayer.PausedState]:
                iconPath = IconsHub.ControlPlay
            icon = QIcon(iconPath)
            self.playAction.setIcon(icon)
            if self.timerFlag:
                if newState == QMediaPlayer.PlayingState:
                    self.timeStart = time.time()
                else:
                    self.timeSpan += time.time() - self.timeStart

    def media_status_changed(self, status):
        if status == QMediaPlayer.EndOfMedia:
            self.music_finished()

    def music_finished(self):
        if self.errorType == Configures.NoError:
            self.next_song()

    def play_music(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def stop_music_but_timing(self):
        self.mediaPlayer.stop()
        self.seekSlider.setValue(0)
        self.media_player_notify_signal.emit(-0.5)

    def stop_music(self):
        self.stop_music_but_timing()
        if self.timerFlag:
            self.timerFlag = False
            InfosList = [
                self.playedDate,
                self.musicFileName,
                self.musicName,
                self.artistName,
                self.album,
                "%i" % change_mmss_to_seconds(self.totalTime),
                "%.1f" % self.timeSpan,
                self.playlistName,
                self.sourcePath,
                "%i" % (self.title in self.lovedSongs),
                self.sourceTrace,
                Configures.Playmodes[self.playmode],
                "%i" % self.clickPlayFlag,
            ]
            log_playback_history(organized_list_as_str(InfosList))
            self.songinfosManager.update_time_span_relate_of_item(self.musicFileName, self.timeSpan, self.clickPlayFlag)
            self.clickPlayFlag = False

    def get_next_random_row(self):
        listTemp = list(self.playlist.get_ids() - set(self.nearPlayedSongs))
        ran = random.randint(0, len(listTemp) - 1)
        return self.playlist.get_items_queue().index(listTemp[ran])

    def get_next_single_row(self):
        nextRow = self.currentSourceRow
        if nextRow < 0:
            nextRow = 0
        return nextRow

    def get_next_order_row(self, reverse=False):
        if reverse:
            if self.currentSourceRow < 0:
                self.currentSourceRow = 0
            return (self.currentSourceRow - 1) % self.playlist.length()
        return (self.currentSourceRow + 1) % self.playlist.length()

    def previous_song(self):
        self.play_source_on_next_row(reverse=True)

    def next_song(self):
        self.play_source_on_next_row()

    def play_source_on_next_row(self, reverse=False):
        if not self.playlist.length():
            return
        if self.mediaPlayer.position() > 20:
            self.music_ended_signal.emit()
        nextRow = 0
        if self.playmode == Configures.PlaymodeRandom:
            nextRow = self.get_next_random_row()
        elif self.playmode == Configures.PlaymodeOrder:
            nextRow = self.get_next_order_row(reverse)
        elif self.playmode == Configures.PlaymodeSingle:
            nextRow = self.get_next_single_row()
        self.set_media_source_at_row(nextRow)

    def current_media_changed(self):
        if not self.playlist.length():
            return
        self.current_media_changed_signal.emit()
        self.update_parameters()
        self.update_near_played_queue()
        self.check_favorite()

    def update_parameters(self):
        self.currentSourceRow = self.playlist.get_current_row()
        self.musicTitleLabel.setText(self.title)
        self.playAction.setText(self.musicName)
        imagePath = SearchOnline.get_artist_image_path(self.artistName)
        if imagePath:
            pixmap = QPixmap(imagePath)
        else:
            pixmap = QPixmap(IconsHub.Anonymous)
        self.artistHeadLabel.setPixmap(pixmap)
        musicId = self.playlist.get_music_id_at(self.currentSourceRow)
        self.update_window_lyric_signal.emit(self.title, musicId)

    def update_near_played_queue(self):
        self.currentSourceId = self.playlist.get_music_path_at(self.currentSourceRow)
        if self.playlist.get_name() == Configures.PlaylistOnline:
            self.currentSourceId = self.playlist.get_music_id_at(self.currentSourceRow)
        if self.currentSourceId not in self.nearPlayedSongs:
            self.nearPlayedSongs.append(self.currentSourceId)
        while len(self.nearPlayedSongs) >= self.playlist.length() * 4 / 5:
            del self.nearPlayedSongs[0]

    def add_title_into_loved_songs(self, title):
        self.lovedSongs.append(title)
Ejemplo n.º 12
0
class MusicPlayer(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.options = self.parent().options

        self.ffmpeg = self.options['paths']['ffmpeg_bin']
        self.thumbnails = self.options['paths']['thumbnails']
        self.thumb_width = self.options['thumbnail']['width']
        self.thumb_height = self.options['thumbnail']['height']

        self.jumping = False
        self.blocked = False
        self.durations = {}
        self.playback_value = 0

        self.text = ["None", "Repeat", "Random"]
        self.playlist_list = []
        self.values = [
            QMediaPlaylist.Loop, QMediaPlaylist.CurrentItemInLoop,
            QMediaPlaylist.Random
        ]

        # Thumbnail widget
        self.image_label = QLabel()

        # Control widgets
        self.playButton = QToolButton(clicked=self.play)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

        self.stopButton = QToolButton(clicked=self.stop)
        self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.stopButton.setEnabled(False)

        self.playbackButton = QToolButton(clicked=self.playback_mode)
        self.playbackButton.setText(self.text[0])

        self.nextButton = QToolButton(clicked=self.next_song)
        self.nextButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))

        self.previousButton = QToolButton(clicked=self.previous_song)
        self.previousButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipBackward))

        self.muteButton = QToolButton(clicked=self.mute_clicked)
        self.muteButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume))

        self.volumeSlider = QSlider(Qt.Horizontal,
                                    sliderMoved=self.change_volume)
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setPageStep(1)
        self.volumeSlider.setValue(50)

        # Player and playlist setup

        self.player = QMediaPlayer()
        self.player.setVolume(50)
        self.player.stateChanged.connect(self.waveform)

        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(self.values[0])
        self.playlist.setCurrentIndex(1)

        self.player.setPlaylist(self.playlist)

        self.playlistModel = PlaylistModel()
        self.playlistModel.setPlaylist(self.playlist)

        self.playlistView = QListView()
        self.playlistView.setModel(self.playlistModel)
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))
        self.playlistView.activated.connect(self.jump)
        self.playlistView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.playlistView.customContextMenuRequested.connect(
            self.list_view_menu)
        self.playlist.currentIndexChanged.connect(
            lambda position: self.change_thumbnail(position))

        song_search = QLineEdit()
        song_search.textChanged.connect(self.search)
        song_search.setClearButtonEnabled(True)

        # Playlist
        self.playlist_name = QComboBox()
        self.playlist_name.currentTextChanged.connect(self.switch_playlist)
        self.refresh_lists()

        self.up_button = QToolButton(clicked=self.move_up)
        self.up_button.setIcon(self.style().standardIcon(QStyle.SP_ArrowUp))
        self.down_button = QToolButton(clicked=self.move_down)
        self.down_button.setIcon(self.style().standardIcon(
            QStyle.SP_ArrowDown))

        # Sound wave widget

        self.wave_graphic = WaveGraphic(self)
        #self.wave_graphic.hide()

        # Testing slider again
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)

        # Shortcuts
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self, song_search.setFocus)

        # Layouts setup

        playlist_layout = QHBoxLayout()
        playlist_layout.addWidget(self.playlist_name)
        playlist_layout.addWidget(self.up_button)
        playlist_layout.addWidget(self.down_button)

        control_layout = QHBoxLayout()
        control_layout.setContentsMargins(0, 0, 0, 0)
        control_layout.addWidget(self.stopButton)
        control_layout.addWidget(self.previousButton)
        control_layout.addWidget(self.playButton)
        control_layout.addWidget(self.nextButton)
        control_layout.addWidget(self.muteButton)
        control_layout.addWidget(self.volumeSlider)
        control_layout.addWidget(self.playbackButton)

        display_layout = QVBoxLayout()
        display_layout.addWidget(song_search)
        display_layout.addWidget(self.playlistView)
        display_layout.addLayout(playlist_layout)

        music_layout = QVBoxLayout()
        music_layout.addWidget(self.image_label)
        music_layout.addWidget(self.slider)
        music_layout.addLayout(control_layout)

        main_layout = QHBoxLayout()
        main_layout.addLayout(music_layout)
        main_layout.addLayout(display_layout)

        main_2_layout = QVBoxLayout()
        main_2_layout.addLayout(main_layout)
        main_2_layout.addWidget(self.wave_graphic)

        self.setLayout(main_2_layout)

    def waveform(self, status):
        if status == QMediaPlayer.PlayingState:
            self.wave_graphic.start()
        elif status == QMediaPlayer.PausedState:
            self.wave_graphic.pause()
        else:
            self.wave_graphic.stop()

    def list_view_menu(self, point):
        menu = QMenu("Menu", self)
        recommend_action = QAction('&Recommend Songs', self)
        menu.addAction(recommend_action)

        # TODO: [FEATURE] add rename song
        recommend_action.triggered.connect(
            lambda: self.parent().call_download_manager(self.get_links()))

        rename_action = QAction('&Rename', self)
        menu.addAction(rename_action)

        # TODO: [FEATURE] add rename song
        rename_action.triggered.connect(lambda: print("rename"))

        # Show the context menu.
        menu.exec_(self.playlistView.mapToGlobal(point))

    def get_links(self):
        title = self.playlistView.selectedIndexes()[0].data()
        link = getYoutubeURLFromSearch(title)
        if len(link) > 1:
            return youtube_recommendations(link)

    def move_up(self):
        index = self.playlistView.currentIndex().row()
        if index - 1 >= 0:
            item, above = self.playlist.media(index), self.playlist.media(
                index - 1)
            self.playlist.removeMedia(index)
            self.playlist.removeMedia(index - 1)
            self.playlist.insertMedia(index - 1, item)
            self.playlist.insertMedia(index, above)
            self.blocked = True
            self.playlistView.setCurrentIndex(
                self.playlistModel.index(index - 1, 0))
            self.blocked = False
            self.stop()

    def move_down(self):
        index = self.playlistView.currentIndex().row()
        if index + 1 <= self.playlistModel.rowCount():
            item, below = self.playlist.media(index), self.playlist.media(
                index + 1)
            self.playlist.removeMedia(index + 1)
            self.playlist.removeMedia(index)
            self.playlist.insertMedia(index, below)
            self.playlist.insertMedia(index + 1, item)
            self.blocked = True
            self.playlistView.setCurrentIndex(
                self.playlistModel.index(index + 1, 0))
            self.blocked = False
            self.stop()

    def search(self, part_of_song):
        for index in range(self.playlistModel.rowCount()):
            item = self.playlistModel.data(self.playlistModel.index(
                index, 0)).lower()
            self.playlistView.setRowHidden(index,
                                           part_of_song.lower() not in item)

    def change_thumbnail(self, position=0):

        self.playlistView.setCurrentIndex(self.playlistModel.index(
            position, 0))

        song = self.playlistView.selectedIndexes()[0].data()
        if self.wave_graphic.is_song_cached(song):
            self.wave_graphic.load_waves(song)
        else:
            wc_ = WaveConverter(song, self.wave_graphic.set_wav)
            wc_.convert()

        if self.playlistView.currentIndex().data() is None or self.blocked:
            return

        max_ratio = 0
        img = None

        for item in listdir(self.thumbnails):
            if item.endswith('.jpg'):
                ratio = similar(
                    item,
                    self.playlistView.currentIndex().data().replace(
                        '.mp3', '.jpg'))
                if ratio > max_ratio:
                    max_ratio = ratio
                    img = item

        if img:
            p = QPixmap(self.thumbnails + img)
            self.image_label.setPixmap(
                p.scaled(self.thumb_width, self.thumb_height,
                         Qt.KeepAspectRatio))

    def switch_playlist(self, current_text):
        self.playlist.clear()
        if current_text == "No Playlist":
            self.refresh()
        else:
            if read_playlist(current_text):
                songs = read_playlist(current_text).split('\n')
                for song in songs:
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(song)))

    def refresh(self):
        # Change it so it will go to same song.
        if self.playlist_name.currentText() != "No Playlist":
            return

        paths = fetch_options()['paths']['music_path'].split(';')

        current_songs = [
            self.playlistModel.data(self.playlistModel.index(row, 0))
            for row in range(self.playlistModel.rowCount())
        ]

        for path in paths:
            if not path:
                continue
            for item in listdir(path):
                if isfile(join(path, item)) and item.endswith(".mp3") and (
                        item not in current_songs):
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(join(path, item))))

    def refresh_lists(self):
        path = fetch_options()['paths']['playlist']
        self.playlist_name.clear()
        self.playlist_list = ["No Playlist"]
        self.playlist_name.addItem("No Playlist")
        for item in listdir(path):
            if isfile(join(path, item)) and item.endswith(".lst"):
                self.playlist_list.append(item.split('.')[0])
                self.playlist_name.addItem(item.split('.')[0])

    def playback_mode(self):
        # Normal -> Loop -> Random
        def up_value(value, max_value=3):
            if value + 1 == max_value:
                return 0
            return value + 1

        self.playback_value = up_value(self.playback_value)
        self.playlist.setPlaybackMode(self.values[self.playback_value])
        self.playbackButton.setText(self.text[self.playback_value])

    def jump(self, index):
        if index.isValid() and not self.blocked:
            self.playlist.setCurrentIndex(index.row())
            self.jumping = True
            self.play()

    def play(self):
        if self.blocked:
            return
        if self.player.state() != QMediaPlayer.PlayingState or self.jumping:
            self.player.play()
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
            self.jumping = False
        else:
            self.player.pause()
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))
        self.stopButton.setEnabled(True)

    def change_volume(self, value):
        self.player.setVolume(value)

    def stop(self):
        if self.player.state() != QMediaPlayer.StoppedState:
            self.player.stop()
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.stopButton.setEnabled(False)

    def next_song(self):
        self.playlist.next()
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

    def previous_song(self):
        self.playlist.previous()
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

    def mute_clicked(self):
        self.player.setMuted(not self.player.isMuted())
        self.muteButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume if not self.player.isMuted() else QStyle.
            SP_MediaVolumeMuted))

    def durationChanged(self, duration):
        duration /= 1000
        self.slider.setMaximum(duration)

    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)
Ejemplo n.º 13
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.playlist = []
        self.files = []

        self.menu = QMenu()
        self.menu.addAction(icons["ti-file"] + " Open a file",
                            lambda: print("file"))
        self.menu.addAction(icons["ti-files"] + " Open a files",
                            lambda: print("files"), "Ctrl+O")
        self.menu.addAction(icons["ti-folder"] + " Open a folder",
                            lambda: print("folder"), "Ctrl+Shift+O")
        self.menu.setStyleSheet("font-family: themify;")

        self.setMinimumSize(500, 60)
        self.move(100, 100)

        self.player = QMediaPlayer()
        self.titleBar = CustomTitleBar(self, "AnosePlayer", "ti-music-alt")
        self.prevBut = QPushButton(icons["ti-control-skip-backward"], self)
        self.pausBut = QPushButton(icons["ti-control-pause"], self)
        self.nextBut = QPushButton(icons["ti-control-skip-forward"], self)
        self.progress = QProgressBar(self)
        self.openFile = QPushButton(icons["ti-plus"], self)

        self.prevBut.setObjectName("Control")
        self.pausBut.setObjectName("Control")
        self.nextBut.setObjectName("Control")
        self.openFile.setObjectName("Control")

        self.progress.setTextVisible(False)
        self.openFile.setMenu(self.menu)
        self.player.setVolume(10)

        self.player.positionChanged.connect(self.updateTime)
        self.player.durationChanged.connect(self.showDuration)
        self.player.mediaChanged.connect(self.changedMedia)
        self.player.volumeChanged.connect(self.showVolume)
        self.player.stateChanged.connect(lambda *args: print(args))
        self.prevBut.clicked.connect(self.previousSong)
        self.pausBut.clicked.connect(self.playPause)
        self.nextBut.clicked.connect(self.nextSong)

        self.player.setMedia(
            QMediaContent(
                QUrl.fromLocalFile(
                    "/home/martin/Music/Principal/System Of A Down - ATWA.mp3")
            ))

        with open("theme.css", "r") as file:
            self.setStyleSheet(file.read())

    def oFile(self):
        file = QFileDialog.getExistingDirectory(
            self, "QFileDialog.getOpenFileName()", "",
            "All Files (*);;Python Files (*.py)")

    # def oFiles(self):
    def oFolde(self):
        file = QFileDialog.getExistingDirectory(
            self, "QFileDialog.getOpenFileName()", "",
            "All Files (*);;Python Files (*.py)")

    def updateTime(self, time):
        self.progress.setValue(time)
        self.progress.repaint()
        print(self.progress.value())

    def showDuration(self, totalTime):
        self.progress.setMaximum(totalTime)
        print(self.progress.maximum())

    def changedMedia(self, *args):
        print(args)

    def showVolume(self, volume):
        print(volume)

    def changeTime(self, time):
        self.player.setPosition(time)

    def previousSong(self):
        if self.i - 1 >= 0:
            self.i -= 1
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(self.playlist[self.i])))

    def playPause(self):
        if self.player.state() == 1:
            self.player.pause()
            self.pausBut.setText(icons["ti-control-play"])
        else:
            self.player.play()
            self.pausBut.setText(icons["ti-control-pause"])

    def nextSong(self):
        if self.i + 1 >= len(self.playlist):
            self.playlist.append(choice(self.files))
        self.i += 1
        self.player.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.playlist[self.i])))

    def resizeEvent(self, e):
        self.titleBar.setGeometry(0, 0, self.width(), 20)
        self.prevBut.setGeometry(0, 20, 30, 30)
        self.pausBut.setGeometry(30, 20, 30, 30)
        self.nextBut.setGeometry(60, 20, 30, 30)
        self.progress.setGeometry(100, 25, 390, 20)
        self.openFile.setGeometry(0, 50, 30, 30)
Ejemplo n.º 14
0
class Player(QGraphicsVideoItem):

    isSubtitle = pyqtSignal(bool)
    subtitlePos = pyqtSignal(int)
    def __init__(self, parent=None):
        super().__init__()
        self.parent = parent

        self.player = QMediaPlayer()
        self.player.setVolume(int(settings().value("Player/volume") or 100))
        self.player.setVideoOutput(self)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.timerPos)

        self.player.currentMediaChanged.connect(self.signalStart)
        self.player.currentMediaChanged.connect(self.parent.subtitleitem.subtitleControl)
        self.player.currentMediaChanged.connect(self.videoConfigure)
        """self.player.mediaStatusChanged.connect(self.metadata)

    def metadata(self, data):
        if data and self.player.isMetaDataAvailable():
            print(self.player.metaData("VideoCodec"))"""

    def videoConfigure(self, media):
        video_name = os.path.basename(media.canonicalUrl().toLocalFile())
        videos = settings().value("Player/video_names") or []
        videos_time = settings().value("Player/videos_time") or []
        try:
            self.player.setPosition(int(videos_time[videos.index(video_name)]))
        except ValueError:
            pass

    def timerStart(self):
        self.timer.start(200)

    def signalStart(self, content):
        srt = content.canonicalUrl().toLocalFile().split(".")
        srt.pop(-1)
        srt.append("srt")
        srt = ".".join(srt)
        if QFile.exists(srt):
            self.isSubtitle.emit(True)
            self.timer.start(100)
        else:
            self.isSubtitle.emit(False)
            self.timer.stop()

    def timerPos(self):
        self.subtitlePos.emit(self.player.position())

    def playerPlayOrOpen(self, arg=None):
        if type(arg) == list and len(arg) > 1:
            content = QMediaContent(QUrl.fromLocalFile(arg[1]))
            self.player.setMedia(content)
            self.play()

    def addVideo(self, video):
        content = QMediaContent(QUrl.fromLocalFile(video))
        self.player.setMedia(content)
        self.play()

    def addYoutubeVideo(self, video):
        dm = DownloadManager(self)

        content = QMediaContent(dm.addUrl(video))
        self.player.setMedia(content)
        self.play()

    def sliderChanged(self, pos):
        self.player.setPosition(pos)

    def play(self):
        self.player.play()

    def stop(self):
        self.player.stop()

    def pause(self):
        self.player.pause()

    def setMuted(self, mute):
        self.player.setMuted(mute)

    def mutedState(self):
        if self.player.isMuted():
            self.setMuted(False)
        else:
            self.setMuted(True)

    def isMuted(self):
        return  self.player.isMuted()

    def setVolume(self, value):
        self.player.setVolume(value)

    def volume(self):
        return self.player.volume()
Ejemplo n.º 15
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']))
Ejemplo n.º 16
0
class EventAction():
    def __init__(self):
        #self.parent = parent
        self.isLoop = 0         #0循环列表,1单曲循环
        self.isRandom = 0       #0不随机,1随机
        self.fileList = []      #曲目名称列表
        self.randomList =[]     #播放列表
        self.soundID = 0        #当前歌曲ID
        self.playStat = False  #当前播放状态 (0未播放,1播放)
        self.openPath = "F:/mp3/" #歌曲目录
        self.isPreview = 0       #试用开关,0正常播放,1列表中的歌曲每首歌曲放10秒
        self.currentVolume = 0.1#默认的起始音量
        self.isInitPlay = 1     #是否是初始播放
        #==>>打开目录
        self.config=configparser.ConfigParser()
        self.config.read('config.ini')
        self.openDir()
        #打开目录<<==
        self.playObj = QMediaPlayer()

        self.currentImg = ""    #当前图片
        self.songText = {}      #歌词
        self.songTextKey=[]     #歌词KEY



    #打开歌曲目录
    def openDir(self):
        self.openPath = self.config.get('Save','musicPath')
        isMusicDir = os.path.isdir(self.openPath)#检查是否为目录
        if isMusicDir:
            dirFile = os.listdir(self.openPath)#目录中的所有文件
            #遍历有效音乐文件
            i=0;
            for file in dirFile:
                fileName,fileType=os.path.splitext(file)
                if fileType==".mp3" or fileType==".wav":
                    self.fileList.append(file)
                    self.randomList.append(i)
                    i+=1
        if self.isRandom==1:
            self.shuffleMusic(1)

    #随机(打乱播放顺序)
    def shuffleMusic(self,isshuffle):
        if isshuffle:
            random.shuffle(self.randomList)#乱序
        else:
            self.randomList.sort()#排序

    #初始化播放
    def initPlay(self):
        self.soundID = int(self.config.get('Save','soundID'))
        self.playStat = self.config.get('Save','playStat')
        self.pastTime = self.config.getint('Save','pastTime')
        self.currentVolume = self.config.getint('Save','volume')
        self.isRandom = self.config.getint('Save','isRandom')
        self.isLoop = self.config.getint('Save','isLoop')

        if self.soundID!="":
            self.play(self.soundID)
        if self.isRandom:#打乱列表
            self.shuffleMusic(1)
        self.playObj.setVolume(self.currentVolume)


    #播放
    def play(self,i):
        source = self.openPath + self.fileList[i]
        self.playObj.setMedia(QMediaContent(QUrl.fromLocalFile(source)))
        #解析文件中的ID3V2
        self.currentImg = ""
        f = QFile(source)
        if f.open(QIODevice.ReadOnly):
            #读取标签
            headData = f.read(10)
            data = headData[:0]
            if self.id3v2(headData):#检测是否有ID3
                #标签的大小计算
                tag = headData[6:10]
                tagSize = (tag[0]&0x7f)*0x200000+(tag[1]&0x7f)*0x4000+(tag[2]&0x7f)*0x80+(tag[3]&0x7f)
                data =f.read(tagSize)
                while len(data)>10:
                    data = self.resolve(data)
        f.close()
        self.playObj.play()

    def testPlay(self):
        #ps =QMediaMetaData()
        #print("QMediaMetaData",ps)
        #print("metaData",self.playObj.metaData(QMediaMetaData.Title))
        #print("position",self.playObj.position())
        #print("playlist",self.playObj.playlist)
        #print("availability",self.playObj.availability())
        #print("bufferStatus",self.playObj.bufferStatus())
        #print("currentMedia",self.playObj.currentMedia())
        #print("currentNetworkConfiguration",self.playObj.currentNetworkConfiguration())
        #print("duration",self.playObj.duration())
        #print("error",self.playObj.error())
        #print("errorString",self.playObj.errorString())
        #print("isAudioAvailable",self.playObj.isAudioAvailable())
        #print("isMuted",self.playObj.isMuted())
        #print("isSeekable",self.playObj.isSeekable())
        #print("media",self.playObj.media())
        #print("media:::::::A",self.playObj.media().canonicalResource().audioBitRate())
        #print("media:::::::B",self.playObj.media().canonicalResource().audioCodec())
        #print("media:::::::C",self.playObj.media().canonicalResource().channelCount())
        #print("media:::::::D",self.playObj.media().canonicalResource().dataSize())
        #print("media:::::::e",self.playObj.media().canonicalResource().isNull())
        #print("media:::::::f",self.playObj.media().canonicalResource().language())
        #print("media:::::::g",self.playObj.media().canonicalResource().mimeType())
        #print("media:::::::h",self.playObj.media().canonicalResource().request())
        #print("isVideoAvailable",self.playObj.isVideoAvailable())
        #print("mediaStatus",self.playObj.mediaStatus())
        #print("mediaStream",self.playObj.mediaStream())
        #print("playbackRate",self.playObj.playbackRate())
        #print("state",self.playObj.state())
        #print("volume",self.playObj.volume())
        # print("volume",self.playObj.filename)
        pass



    #换歌之前先停止,释放内存
    def stopPlay(self):
        self.playObj.pause()

    #上一首
    def prevPlay(self):
        self.stopPlay()
        if self.isRandom:
            key = self.searchID(self.soundID)-1
            if key<0:
                key=0
            self.soundID = self.randomList[key]
        else:
            self.soundID-=1
            if self.soundID< 0:
                self.soundID = len(self.randomList)-1
        self.play(self.soundID)

    #下一首
    def nextPlay(self):
        self.stopPlay()
        if self.isRandom:
            key = self.searchID(self.soundID)+1
            if key>(len(self.randomList)-1):
                key=len(self.randomList)-1
            self.soundID = self.randomList[key]
        else:
            self.soundID+=1
            if self.soundID > (len(self.randomList)-1):
                self.soundID = 0
        #print("next:::",self.soundID)
        self.play(self.soundID)

    #快退
    def rewindPlay(self):
        #print("<<")
        rewindTime = int(self.playObj.position()) - 10*1000
        if rewindTime < 0:
            rewindTime = 0
        self.playObj.setPosition(rewindTime)

    #快进
    def forwardPlay(self):
        #print(">>")
        forwardTime = int(self.playObj.position()) + 10*1000
        if forwardTime > int(self.playObj.duration()):
            forwardTime = int(self.playObj.duration())
        self.playObj.setPosition(forwardTime)

    #播放/暂停
    def playORpause(self):
        if self.playObj.state()==1:
            self.playObj.pause()
        else:
            self.playObj.play()

    #音量加
    def raisevolPlay(self):
        self.playObj.setVolume(self.playObj.volume()+10)
        self.currentVolume = self.playObj.volume()
    #音量减
    def lowervolPlay(self):
        self.playObj.setVolume(self.playObj.volume()-10)
        self.currentVolume = self.playObj.volume()

    #静音
    def mutePlay(self):
        if self.playObj.isMuted():
            self.playObj.setMuted(False)
        else:
            self.playObj.setMuted(True)
    #volume

    #跟据v找K
    def searchID(self,v):
        for index, item in enumerate(self.randomList):
            if item ==v:
                return index
        return 0

    #解析文件中是否有id3v2
    def id3v2(self,headData):
        if str(headData[:3],encoding=("utf-8")) != "ID3":
            return False
        return True

    #解析文件中的歌词与图片
    def resolve(self,data):
        tagName =  str(data[:4],encoding=("utf-8"))
        size = data[4:8]
        #sizeS = size[0]*0x1000000 + size[1]*0x10000 + size[2]*0x100 + size[3]
        sizeS=int.from_bytes(size, byteorder='big')
        flags = data[8:10]
        tagContent = data[10:sizeS+10]

        if tagName=="TEXT":#歌词
            #print("歌词")
            condingType=int.from_bytes(tagContent[:1], byteorder='big')
            if condingType == 0:#0代表字符使用ISO-8859-1编码方式;
                try:
                    content = str(tagContent[1:],encoding="gbk")
                except:
                    content =""
            elif condingType == 1:#1代表字符使用UTF-16编码方式;
                try:
                    content = str(tagContent[1:],encoding="UTF-16")
                except:
                    content =""
            elif condingType == 2:#2代表字符使用 UTF-16BE编码方式;
                content =""
            elif condingType == 3:#3代表字符使用UTF-8编码方式。
                try:
                    content = str(tagContent[1:],encoding="UTF-8")
                except:
                    content =""
            if content!="":
                temp={}
                self.songTextKey=[]
                contentSplit = content.splitlines()
                for k in range(len(contentSplit)):
                    if contentSplit[k][1].isdigit():
                        xxx = contentSplit[k].split("]")
                        tempKey = "%d" %(int(xxx[0][1:3])*60 +int(xxx[0][4:6]) )
                        temp[str(tempKey)] = xxx[1]
                        self.songTextKey.append(tempKey)
                    else:
                        endKey = contentSplit[k].find("]",0)
                        self.songTextKey.append(k)
                        temp[str(k)] = contentSplit[k][1:endKey]
                self.songText = temp
            else:
                self.songText = {}
        elif tagName=="APIC":#图片
            #print("图片")
            self.currentImg = tagContent[17:]
        return data[10+sizeS:]
Ejemplo n.º 17
0
class MainUi(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.player = QMediaPlayer(self)

    def init_ui(self):
        self.setFixedSize(550, 325)
        self.main_widget = QtWidgets.QWidget()  # 创建窗口主部件
        self.main_layout = QtWidgets.QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局

        self.left_widget = QtWidgets.QWidget()  # 创建左侧部件
        self.left_widget.setObjectName('left_widget')
        self.left_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.left_widget.setLayout(self.left_layout)  # 设置左侧部件布局为网格
        self.left_widget.setStyleSheet('''
            QPushButton{border:none;color:white;}
            QPushButton#left_label{
                border:none;
                border-bottom:1px solid white;
                font-size:18px;
                font-weight:700;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;}
        ''')

        self.right_widget = QtWidgets.QWidget()  # 创建右侧部件
        self.right_widget.setObjectName('right_widget')
        self.right_layout = QtWidgets.QGridLayout()
        self.right_widget.setLayout(self.right_layout)  # 设置右侧部件布局为网格
        self.right_bar_widget = QtWidgets.QWidget()  # 右侧顶部搜索框部件
        self.right_bar_layout = QtWidgets.QGridLayout()  # 右侧顶部搜索框网格布局

        self.right_bar_widget.setLayout(self.right_bar_layout)
        self.search_icon = QtWidgets.QLabel(chr(0xf002) + ' ' + '搜索  ')
        self.search_icon.setFont(qtawesome.font('fa', 16))
        self.right_bar_widget_search_input = QtWidgets.QLineEdit("")
        self.right_bar_widget_search_input.setPlaceholderText(
            "输入歌手、歌曲或用户,回车进行搜索")
        self.right_bar_layout.addWidget(self.search_icon, 0, 0, 1, 1)
        self.right_bar_layout.addWidget(self.right_bar_widget_search_input, 0,
                                        1, 1, 8)
        self.right_layout.addWidget(self.right_bar_widget, 0, 0, 1, 9)
        self.right_bar_widget_search_input.returnPressed.connect(
            self.Get_song_name)

        self.right_bar_widget_search_input.setStyleSheet('''QLineEdit{
                    border:1px solid gray;
                    width:300px;
                    border-radius:10px;
                    padding:2px 4px;
            }''')
        self.right_widget.setStyleSheet('''
            QWidget#right_widget{
                color:#232C51;
                background:white;
                border-top:1px solid darkGray;
                border-bottom:1px solid darkGray;
                border-right:1px solid darkGray;
                border-top-right-radius:10px;
                border-bottom-right-radius:10px;
            }
            QLabel#right_lable{
                border:none;
                font-size:16px;
                font-weight:700;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
        ''')

        # icon = QtGui.QIcon()
        # icon.addPixmap(QtGui.QPixmap("ico/瓜板.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        # self.setWindowIcon(icon)
        # self.setToolTip("")

        self.main_layout.addWidget(self.left_widget, 0, 0, 12,
                                   2)  # 左侧部件在第0行第0列,占8行3列
        self.main_layout.addWidget(self.right_widget, 0, 2, 12,
                                   10)  # 右侧部件在第0行第3列,占8行9列
        self.setCentralWidget(self.main_widget)  # 设置窗口主部件

        self.left_close = QtWidgets.QPushButton("")  # 关闭按钮
        self.left_visit = QtWidgets.QPushButton("")  # 空白按钮
        self.left_mini = QtWidgets.QPushButton("")  # 最小化按钮

        self.left_close.setFixedSize(15, 15)  # 设置关闭按钮的大小
        self.left_visit.setFixedSize(15, 15)  # 设置按钮大小
        self.left_mini.setFixedSize(15, 15)  # 设置最小化按钮大小

        self.left_layout.addWidget(self.left_mini, 0, 0, 1, 1)  # 放置最小化按钮
        self.left_layout.addWidget(self.left_close, 0, 2, 1, 1)  # 放置关闭按钮
        self.left_layout.addWidget(self.left_visit, 0, 1, 1, 1)  # 放置空白按钮

        self.left_close.setStyleSheet(
            '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}'''
        )
        self.left_visit.setStyleSheet(
            '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}'''
        )
        self.left_mini.setStyleSheet(
            '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}'''
        )

        self.left_close.clicked.connect(self.left_close_event)  # 添加关闭功能

        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)  # 隐藏边框
        self.setWindowOpacity(0.95)  # 设置窗口透明度
        # self.setAttribute(QtCore.Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.main_layout.setSpacing(0)

    # 鼠标长按事件
    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()
            self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))

    # 鼠标移动事件
    def mouseMoveEvent(self, QMouseEvent):
        if QtCore.Qt.LeftButton and self.m_drag:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)
            QMouseEvent.accept()

    # 鼠标释放事件
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

    def left_close_event(self):
        self.close()

    def Get_song_name(self):
        song_name = self.right_bar_widget_search_input.text()
        # 提取歌曲id
        a, song_id = Cloud_Music_API.single_search(song_name)
        #print(song_id)
        # 获取url
        song_url = Cloud_Music_API.song_url(song_id[1])
        # 播放音乐
        content = QMediaContent(QtCore.QUrl(song_url))
        self.player.setMedia(content)
        self.player.setVolume(30)
        self.player.play()
        self.duration = self.player.duration()  # 音乐的时长
Ejemplo n.º 18
0
class AudioPlayer(QMainWindow):

    def __init__(self):

        super(AudioPlayer, self).__init__()
        self.setGeometry(150, 150, 600, 450)
        self.setWindowTitle('Prototype!!')

        self.isButtonClick = False
        self.current_time = 0
        self.media_obj = audiosegment.empty()
        self.play_process = threading.Thread(target=play, args=(self.media_obj,))

        self.initUI()

    def initUI(self):
        menu = self.menuBar()  # create menu bar
        file_menu = menu.addMenu('File')  # create file button
        options_menu = menu.addMenu('Options')  # create options button
        wid = QWidget()
        self.setCentralWidget(wid)

        # create 'Open FIle' actions, add to 'File' button
        open_file = QAction('Open File', self)
        open_file.triggered.connect(self.openFile)
        open_file.setShortcut("Ctrl+O")
        file_menu.addAction(open_file)

        # create 'Close File' action, add to 'File' button
        close_file = QAction('Close File', self)
        close_file.triggered.connect(self.exit)
        close_file.setShortcut("Ctrl+W")
        file_menu.addAction(close_file)

        # create 'Exit' action, add to 'File' button
        exit_file = QAction('Close File', self)
        exit_file.triggered.connect(self.exit)
        exit_file.setShortcut("Ctrl+W")
        file_menu.addAction(exit_file)

        # create 'Color' action, add to 'Options' button
        color_option = QAction('Color', self)
        color_option.triggered.connect(self.show_color_dialog)
        color_option.setShortcut("Ctrl+2")
        options_menu.addAction(color_option)

        # create 'Shape' action, add to 'Options' button
        shape_option = QAction('Shape', self)
        # shape_option.triggered.connect()
        shape_option.setShortcut("Ctrl+3")
        options_menu.addAction(shape_option)

        # create 'Foliage' action, add to 'Options' button
        foliage_option = QAction('Foliage', self)
        # foliage_option.triggered.connect()
        foliage_option.setShortcut("Ctrl+3")
        options_menu.addAction(foliage_option)

        # Creating button for pause/play
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        videoWidget = QVideoWidget()
        self.pal = QPalette()
        self.pal.setColor(QPalette.Foreground, Qt.green)
        videoWidget.setPalette(self.pal)

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)

        self.songLabel = QLabel()
        self.songLabel.setSizePolicy(QSizePolicy.Preferred,
                                     QSizePolicy.Maximum)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        self.playButton.setShortcut("Space")
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        layout.addLayout(controlLayout)
        layout.addWidget(self.songLabel)
        layout.addWidget(self.errorLabel)

        # Set widget to contain window contents
        wid.setLayout(layout)

        # self.mediaPlayer.setVideoOutput(videoWidget)
        self.player.stateChanged.connect(self.mediaStateChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.durationChanged.connect(self.durationChanged)
        self.player.error.connect(self.handleError)

    def openFile(self):
        song = QFileDialog.getOpenFileName(self, "Open Song", "~", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")
        songName = song[0].split("/")
        songName = songName[-1].split(".")
        self.songLabel.setText(songName[0])
        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playButton.setEnabled(True)
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.setVolume(100)
                self.player.play()
            else:
                self.playlist.addMedia(QMediaContent(url))

    def exit(self):
        sys.exit()

    def play(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
        else:
            self.player.play()

    def mediaStateChanged(self, state):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

    def setPosition(self, position):
        self.player.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        self.errorLabel.setText("Error: " + self.player.errorString())

    def show_color_dialog(self):
        QColorDialog.getColor()
Ejemplo n.º 19
0
class VideoWindow(QMainWindow):
    """ Class:
    Video player window.
    """

    # Main window size.
    WIN_SIZE = [800, 600]

    def __init__(self, parent=None):
        """ Function:
        Setup user interface of Video player window.
        """

        super(VideoWindow, self).__init__(parent)
        self.setWindowTitle("Video player")
        self.resize(VideoWindow.WIN_SIZE[0], VideoWindow.WIN_SIZE[1])
        self.setWindowIcon(self.style().standardIcon(QStyle.SP_DriveDVDIcon))

        self.video_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        self.record_start_time = None
        self.record_end_time = None
        self.video_name = ""

        self.widget_video = QVideoWidget()

        self.statusbar = QtWidgets.QStatusBar(self)
        self.setStatusBar(self.statusbar)

        self.button_play = QPushButton()
        self.button_play.setEnabled(False)
        self.button_play.setIcon(self.style().standardIcon(
            QStyle.SP_MediaPlay))
        self.button_play.clicked.connect(self.play_video)

        self.video_slider = QSlider(Qt.Horizontal)
        self.video_slider.setRange(0, 0)
        self.video_slider.sliderMoved.connect(self.set_position)
        self.video_duration = 0

        # Action 'Open'.
        self.action_open = QAction(QIcon('open.png'), '&Open', self)
        self.action_open.setShortcut('Ctrl+O')
        self.action_open.setStatusTip('Open a video')
        self.action_open.triggered.connect(self.open_video)

        # Menu bar.
        self.menu_bar = self.menuBar()
        self.menu_menu = self.menu_bar.addMenu('&Menu')
        self.menu_menu.addAction(self.action_open)

        # Widget.
        self.widget_window = QWidget(self)
        self.setCentralWidget(self.widget_window)

        self.layout_operation = QHBoxLayout()
        self.layout_operation.setContentsMargins(0, 0, 0, 0)
        self.label_rotate = QLabel('Degree of rotation')
        self.combobox_degree = QComboBox()
        degrees = ['0', '90', '180', '270']
        self.combobox_degree.addItems(degrees)
        self.button_subclip_video = QPushButton('Subclip (Video)')
        self.button_subclip_audio = QPushButton('Subclip (Audio)')
        self.layout_operation.addWidget(self.label_rotate)
        self.layout_operation.addWidget(self.combobox_degree)
        self.layout_operation.addWidget(self.button_subclip_video)
        self.layout_operation.addWidget(self.button_subclip_audio)

        self.layout_record = QHBoxLayout()
        self.layout_record.setContentsMargins(0, 0, 0, 0)
        self.button_start = QPushButton('Start')
        self.button_end = QPushButton('End')
        self.button_clear = QPushButton('Clear')
        self.layout_record.addWidget(self.button_start)
        self.layout_record.addWidget(self.button_end)
        self.layout_record.addWidget(self.button_clear)

        self.button_start.clicked.connect(self.record_start)
        self.button_end.clicked.connect(self.record_end)
        self.button_subclip_video.clicked.connect(self.record_subclip_video)
        self.button_subclip_audio.clicked.connect(self.record_subclip_audio)
        self.button_clear.clicked.connect(self.record_clear)

        # Widget layout.
        self.layout_widget = QHBoxLayout()
        self.layout_widget.setContentsMargins(0, 0, 0, 0)
        self.layout_widget.addWidget(self.button_play)
        self.layout_widget.addWidget(self.video_slider)

        self.layout_window = QVBoxLayout()
        self.layout_window.addWidget(self.widget_video)
        self.layout_window.addLayout(self.layout_record)
        self.layout_window.addLayout(self.layout_operation)
        self.layout_window.addLayout(self.layout_widget)

        # Window layout.
        self.widget_window.setLayout(self.layout_window)

        self.video_player.setVideoOutput(self.widget_video)
        self.video_player.stateChanged.connect(self.media_state_changed)
        self.video_player.positionChanged.connect(self.position_changed)
        self.video_player.durationChanged.connect(self.duration_changed)
        self.video_player.error.connect(self.error_control)

        QShortcut(Qt.Key_Up, self, self.arrow_up)
        QShortcut(Qt.Key_Down, self, self.arrow_down)
        QShortcut(Qt.Key_Left, self, self.arrow_left_event)
        QShortcut(Qt.Key_Right, self, self.arrow_right_event)
        QShortcut(Qt.Key_Space, self, self.play_video)

    def arrow_up(self):
        if self.video_player.state() != QMediaPlayer.StoppedState:
            self.video_player.setVolume(
                min(self.video_player.volume() + 10, 100))

    def arrow_down(self):
        if self.video_player.state() != QMediaPlayer.StoppedState:
            self.video_player.setVolume(max(self.video_player.volume() - 10,
                                            0))

    def arrow_left_event(self):
        """ Slot function:
        Action after the key 'arrow left' is pressed.
        Fast-forward to 10 seconds later.
        """

        self.set_position(self.video_slider.value() - 10 * 1000)

    def arrow_right_event(self):
        """ Slot function:
        Action after the key 'arrow right' is pressed.
        Go back to 10 seconds ago.
        """

        self.set_position(self.video_slider.value() + 10 * 1000)

    def mousePressEvent(self, event):
        """ Slot function:
        The starting position of the slider is 50.
        Note: This function still can't not accurately move the slider to the 
        clicked position.
        """

        slider_start_pos = self.video_slider.geometry().topLeft().x()
        if 42 <= self.height() - event.pos().y() <= 62:
            position = self.video_slider.minimum() + (
                event.pos().x() - slider_start_pos
            ) / self.video_slider.width() * self.video_duration
            if position != self.video_slider.sliderPosition():
                self.set_position(position)

    def open_video(self):
        """ Slot function:
        Open a video from the file system.
        """

        video_name, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                                                    QDir.homePath())
        self.video_name = video_name

        if video_name != '':
            self.video_player.setMedia(
                QMediaContent(QUrl.fromLocalFile(video_name)))
            self.button_play.setEnabled(True)
            self.video_player.play()

            index = video_name.rfind('/')
            self.statusbar.showMessage("Info: Playing the video '" +
                                       video_name[(index + 1):] + "' ...")

    def play_video(self):
        """ Slot function:
        The slot function for the 'play' button.
        If the video player is currently paused, then play the video; 
        otherwise, pause the video.
        """

        if self.video_player.state() == QMediaPlayer.PlayingState:
            self.video_player.pause()
        else:
            self.video_player.play()

    def media_state_changed(self, state):
        """ Slot function:
        If the playing state changes, change the icon for the 'play' button.
        If the video player is currently playing, change the icon to 'pause'; 
        otherwise, change the icon to 'play'.
        """

        if self.video_player.state() == QMediaPlayer.PlayingState:
            self.button_play.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.button_play.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def position_changed(self, position):
        """ Slot function:
        Change the position of the slider.
        """

        self.video_slider.setValue(position)

    def duration_changed(self, duration):
        """ Slot function:
        If the duration of the video changed, change the range of the slider.
        This slot function is called after opening a video.
        """

        self.video_slider.setRange(0, duration)
        self.video_duration = duration
        self.record_start_time = 0
        self.record_end_time = 0

    def set_position(self, position):
        """ Slot function:
        Change the progress of the video.
        """

        self.video_player.setPosition(position)

    def error_control(self):
        """ Slot function:
        If an error occurs while opening the video, this slot function is 
        called.
        """

        self.button_play.setEnabled(False)
        self.statusbar.showMessage(
            "Error: An error occurs while opening the video.")

    def record_start(self):
        self.record_start_time = self.video_slider.sliderPosition()
        if self.record_end_time is not None and self.record_end_time != 0 and self.record_start_time > self.record_end_time:
            self.record_start_time, self.record_end_time = self.record_end_time, self.record_start_time

        self._show_record_time()

    def record_end(self):
        self.record_end_time = self.video_slider.sliderPosition()
        if self.record_start_time is not None and self.record_start_time > self.record_end_time:
            self.record_start_time, self.record_end_time = self.record_end_time, self.record_start_time

        self._show_record_time()

    def _show_record_time(self):
        if self.record_start_time is not None and self.record_end_time is not None:
            self.statusbar.showMessage(
                "Info: Starting time: ({}), and Ending time: ({}) (Duration: {})."
                .format(self.record_start_time / 1000,
                        self.record_end_time / 1000,
                        self.video_duration / 1000))

    def _check_duration(self):
        if self.video_name == "":
            self.statusbar.showMessage("Error: Please open a video first.")
        elif self.record_start_time == self.record_end_time:
            self.statusbar.showMessage("Error: Duration can NOT be 0.")
        elif self.record_start_time > self.record_end_time:
            self.statusbar.showMessage(
                "Error: The start time should be earlier than the end time.")
        else:
            return True

        return False

    def record_subclip_video(self):
        if self._check_duration():
            self.statusbar.showMessage(
                "Info: Please wait until the process ends.")
            self.thread = Thread()
            self.thread.set_params(Thread.MSG_CUT_VIDEO, self.video_name,
                                   self.record_start_time / 1000,
                                   self.record_end_time / 1000,
                                   self.combobox_degree.currentText())
            self.thread.signal_return_value.connect(self.thread_done)
            self.thread.start()

    def record_subclip_audio(self):
        if self._check_duration():
            self.statusbar.showMessage(
                "Info: Please wait until the process ends.")
            self.thread = Thread()
            self.thread.set_params(Thread.MSG_EXTRACT_AUDIO, self.video_name,
                                   self.record_start_time / 1000,
                                   self.record_end_time / 1000)
            self.thread.signal_return_value.connect(self.thread_done)
            self.thread.start()

    def record_clear(self):
        self.record_start_time = 0
        self.record_end_time = 0

        self.statusbar.showMessage(
            "Info: Starting time: ({}), and Ending time: ({}).".format(
                self.record_start_time, self.record_end_time))

    def thread_done(self, return_value, video_name):
        if return_value:
            self.statusbar.showMessage(
                "Info: The process has done and saved as {}.".format(
                    video_name))
Ejemplo n.º 20
0
class MainWindow(ui_mainwindow, qtbaseclass):
    # 详情页面
    detail = None
    # 播放列表dock栏,初始隐藏
    playListDockView = None
    # 当前播放列表
    playList = []
    # 当前播放的歌曲在列表中的索引号
    songIndex = 0
    # 当前播放的歌曲
    song = None
    # 播放器
    player = None
    # api
    func = netease
    # 是否循环播放
    loop = True

    # 记录上次音量值
    lastVolume = 0

    def __init__(self, parent=None):
        if parent == None:
            parent = self
        ui_mainwindow.__init__(parent)
        qtbaseclass.__init__(parent)
        self.setupUi(self)
        self.setWindowTitle("Music")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.setWindowIcon(QIcon('resource/format.ico'))
        with open('QSS/mainWindow.qss', 'r') as f:
            style = f.read()
            self.setStyleSheet(style)

        # 初始化
        self.initList()
        self.initPlayWidgets()
        self.initTabWidgets()
        self.initDetailView()
        self.initPlayListDockView()

    def initList(self):
        # 初始化列表信息

        # 设置推荐列表
        self.recommandList.addItem(
            QListWidgetItem(QIcon('resource/music.png'), " 发现音乐"))
        self.recommandList.addItem(
            QListWidgetItem(QIcon('resource/signal.png'), " 私人FM"))
        self.recommandList.addItem(
            QListWidgetItem(QIcon('resource/movie.png'), " MV"))
        self.recommandList.setCurrentRow(0)

        # 设置我的音乐
        self.myList.addItem(
            QListWidgetItem(QIcon('resource/notes.png'), " 本地音乐"))

        # 设置收藏与创建的歌单
        # 未实现(动态添加)

    def initPlayWidgets(self):
        ''' 初始化播放控件状态'''
        self.player = QMediaPlayer(self)
        # self.player.setVolume(100)
        # 设置音量同时设置进度条
        self.volumeSlider.setValue(100)
        self.player.stateChanged.connect(self.slot_player_stateChanged)
        self.player.positionChanged.connect(self.slot_player_positionChanged)
        self.player.durationChanged.connect(self.slot_player_durationChanged)

        # 隐藏暂停按键
        self.pauseButton.hide()
        self.noVolume.hide()

    def initTabWidgets(self):
        # 初始化主窗口中TabWdidget
        self.detailView.hide()
        self.tabWidget.clear()
        netEase = SongsFrame(self)
        self.tabWidget.addTab(netEase, '网易云音乐')

    def initDetailView(self):
        # 初始化详情页
        self.detail = AlbumDetailView(self)
        self.detailView.setWidget(self.detail)
        self.detail.addSongs.connect(self.slot_addSongs)

    def initPlayListDockView(self):
        # 主显示区域添加播放列表DOCK
        self.playListDockView = PlayListDockWidget(self)
        self.playListDockView.hide()  # 初始状态为隐藏
        self.playListDockView.doubleClicked.connect(
            self.slot_playList_doubleClicked)
        self.mainHorizontalLayout.addWidget(self.playListDockView)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.MiddleButton:
            # if event.globalPos().x() > self.pos().x():
            #     print("Y")
            # else:
            #     print('N')
            self.move(event.globalPos())
            event.accept()
        else:
            super().mouseMoveEvent(event)

    def slot_prev_page_clicked(self):
        '''上一页'''
        if self.tabWidget.isHidden():
            self.tabWidget.show()
            self.detailView.hide()

    def slot_next_page_clicked(self):
        '''下一页'''
        # if self.detailView.isHidden():
        #     self.tabWidget.hide()
        #     self.detailView.show()
        pass

    def slot_prev_song_clicked(self):
        '''上一首歌'''
        self.player.stateChanged.disconnect()
        self.songIndex = self.songIndex - 1
        if self.songIndex < 0:
            self.songIndex = 0
        else:
            self.song = self.playList[self.songIndex]
            if self.set_player_media():
                self.player.play()
        self.playListDockView.setSelectRow(self.songIndex)
        self.player.stateChanged.connect(self.slot_player_stateChanged)

    def slot_next_song_clicked(self):
        '''下一首歌'''
        self.player.stateChanged.disconnect()
        self.songIndex = (self.songIndex + 1) % len(self.playList)
        self.song = self.playList[self.songIndex]
        if self.set_player_media():
            self.player.play()

        self.playListDockView.setSelectRow(self.songIndex)
        self.player.stateChanged.connect(self.slot_player_stateChanged)

    def slot_play_clicked(self):
        '''播放 点击事件'''
        if self.player.mediaStatus() > 1 and self.player.mediaStatus() < 7:
            self.player.play()
        else:
            # 未添加 音乐
            QMessageBox.warning(self, '警告', '播放列表为空!请先添加音乐到播放列表。')

    def slot_pause_clicked(self):
        '''暂停 点击事件'''
        self.player.pause()
        # self.playButton.show()
        # self.pauseButton.hide()

    def slot_addSongs(self, songsList):
        '''添加歌曲'''
        # 去重合并列表
        ids = [x.id for x in self.playList]
        for song in songsList:
            if song.id not in ids:
                self.playList.append(song)
                # 播放列表变化,更新列表显示
                self.playListDockView.setList(self.playList)
        # 初始化song
        if self.song == None:
            self.song = self.playList[self.songIndex]
            self.set_player_media()

    def slot_player_stateChanged(self):
        '''播放器状态变化'''
        if not self.playList:
            return

        if self.player.state() == QMediaPlayer.StoppedState:
            if self.loop:
                self.songIndex = (self.songIndex + 1) % len(self.playList)
                self.song = self.playList[self.songIndex]
                if self.set_player_media():
                    self.player.play()
            else:
                self.playButton.show()
                self.pauseButton.hide()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.playButton.show()
            self.pauseButton.hide()
        elif self.player.state() == QMediaPlayer.PlayingState:
            self.playButton.hide()
            self.pauseButton.show()

        self.countTime.setText(self.song.time)

    def slot_player_positionChanged(self, pos):
        '''播放时间改变控件位置'''
        t = pos / 1000
        mins = t // 60
        secs = t % 60
        curTime = QtCore.QTime(0, mins, secs).toString('mm:ss')
        self.currentTime.setText(curTime)
        self.timeSlider.setValue(pos)

    def slot_player_durationChanged(self, duration):
        '''设置进度条最大值'''
        self.timeSlider.setRange(0, duration)

    def set_player_media(self):
        '''设置播放器音乐媒体,成功返回True,否则False'''
        try:
            mp3 = self.func.singsUrl([self.song.id])
            if mp3:
                mp3 = mp3[0]['url']
            self.player.setMedia(QMediaContent(QtCore.QUrl(mp3)))
            return True
        except:
            # 网络异常
            QMessageBox.warning(self, '获取音乐地址失败!请检查网络后重试!', '警告')
            return False

    def slot_playList_clicked(self):
        '''播放列表按钮 点击事件'''
        if self.playListDockView.isHidden():
            self.playListDockView.show()
        else:
            self.playListDockView.hide()

    def slot_playList_doubleClicked(self, songIndex):
        '''播放列表双击事件
        songIndex -- 为当前双击歌曲在列表中的索引号。
        执行动作:立即播放该歌曲
        '''
        self.songIndex = songIndex
        if self.set_player_media():
            self.player.play()

    def slot_volumeSlider_valueChanged(self, value):
        '''音量调节'''
        self.player.setVolume(value)
        if value == 0:
            self.noVolume.show()
            self.volume.hide()
        else:
            self.noVolume.hide()
            self.volume.show()

    def slot_noVolume_clicked(self):
        '''静音按钮点击事件,动作:切成原始音量'''
        # self.volumeSlider.setValue(0)
        self.player.setMuted(False)
        self.noVolume.hide()
        self.volume.show()

    def slot_volume_clicked(self):
        '''音量按钮点击事件,动作:切成静音'''
        # self.volumeSlider.setValue(0)
        self.player.setMuted(True)
        self.noVolume.show()
        self.volume.hide()
Ejemplo n.º 21
0
class MainWindow(QMainWindow):
    def __init__(self, height, width, amount_mines, parent=None):
        super(MainWindow, self).__init__(parent)
        uic.loadUi(Path(__file__).parent / "ui" / "main_window.ui", self)

        # Sounds
        self.sound_beginner_mode = str(
            Path(__file__).parent / "sounds" / "beginner_mode.wav")
        self.sound_intermediate_mode = str(
            Path(__file__).parent / "sounds" / "intermediate_mode.wav")
        self.sound_expert_mode = str(
            Path(__file__).parent / "sounds" / "expert_mode.wav")
        self.sound_beginner_win = str(
            Path(__file__).parent / "sounds" / "beginner_win.wav")
        self.sound_intermediate_win = str(
            Path(__file__).parent / "sounds" / "intermediate_win.wav")
        self.sound_expert_win = str(
            Path(__file__).parent / "sounds" / "expert_win.wav")
        self.sound_flag = str(Path(__file__).parent / "sounds" / "flag.wav")
        self.sound_no_flag = str(
            Path(__file__).parent / "sounds" / "no_flag.wav")
        self.sound_reset = str(
            Path(__file__).parent / "sounds" / "reset_game.wav")
        self.sound_click = str(Path(__file__).parent / "sounds" / "click.wav")
        self.sound_boom = str(Path(__file__).parent / "sounds" / "boom.wav")
        self.sound_bye = str(Path(__file__).parent / "sounds" / "bye.wav")
        self.sound_donate = str(
            Path(__file__).parent / "sounds" / "donate.wav")

        # Qt: connect reset button
        self.pushButton_reset.clicked.connect(self.on_reset_clicked)
        self.pushButton_beginner.clicked.connect(self.change_to_beginner_mode)
        self.pushButton_intermediate.clicked.connect(
            self.change_to_intermediate_mode)
        self.pushButton_expert.clicked.connect(self.change_to_expert_mode)
        self.actionSupport_Tutor_Exilius.triggered.connect(
            self.open_twitch_support_page)
        self.action_About_Qt.triggered.connect(self.on_about_qt)

        self.height = height
        self.width = width
        self.amount_mines = amount_mines
        self.minesweeper = None
        self.current_mode = GameMode.BEGINNER

        # Media Player - to play bye.wav synchronously
        self.player = QMediaPlayer()
        self.player.setVolume(100)

        # Timer
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_lcd_timer)

        self.initial_clicked = False

        palette = self.lcdNumber_amount_mines.palette()
        palette.setColor(palette.WindowText, QtGui.QColor(255, 0, 0))
        palette.setColor(palette.Light, QtGui.QColor(255, 0, 0))
        palette.setColor(palette.Dark, QtGui.QColor(255, 0, 0))

        self.lcdNumber_amount_mines.setPalette(palette)
        self.lcdNumber_playing_time.setPalette(palette)

        self.reset()

    def playsound(self, sound_file):
        try:
            print("Play sound:", sound_file)

            if sound_file == self.sound_bye:
                self.player.setMedia(
                    QMediaContent(QUrl.fromLocalFile(sound_file)))
                self.player.play()
            else:
                QSound.play(sound_file)

        except Exception as e:
            print("Played too fast?")
            print(e)

    def closeEvent(self, event):
        # small hack :)
        # DO FIRST: link next close event to self.force_closeEvent(..)
        self.closeEvent = self.force_closeEvent

        # end of playing 'self.sound_bye' will occure next close()
        # --> self.force_closeEvent(..) will be called
        self.player.stateChanged.connect(self.on_bye_played)

        self.playsound(self.sound_bye)

        event.ignore()

    def force_closeEvent(self, event):
        event.accept()

    def on_bye_played(self, state):
        if state == QMediaPlayer.StoppedState:
            self.close()

    def on_reset_clicked(self):
        self.reset()
        self.playsound(self.sound_reset)

    def on_about_qt(self):
        QMessageBox.aboutQt(self)

    def change_to_beginner_mode(self):
        self.current_mode = GameMode.BEGINNER
        self.height = 8
        self.width = 8
        self.amount_mines = 10
        self.reset()
        self.playsound(self.sound_beginner_mode)

    def change_to_intermediate_mode(self):
        self.current_mode = GameMode.INTERMEDIATE
        self.height = 16
        self.width = 16
        self.amount_mines = 40
        self.reset()
        self.playsound(self.sound_intermediate_mode)

    def change_to_expert_mode(self):
        self.current_mode = GameMode.EXPERT
        self.height = 16
        self.width = 32
        self.amount_mines = 99
        self.reset()
        self.playsound(self.sound_expert_mode)

    def start_game_timer(self):
        self.timer.start(1000)

    def stop_game_timer(self):
        self.timer.stop()

    def update_lcd_timer(self):
        value = self.lcdNumber_playing_time.intValue()
        self.lcdNumber_playing_time.display(value + 1)

    def initialise_field(self):
        self.clear_layout(self.gridLayout)
        button_size = (40, 40)
        font = QFont()
        font.setPointSize(15)
        font.setBold(False)

        if self.current_mode == GameMode.INTERMEDIATE:
            font.setPointSize(11)
            button_size = (32, 32)
        elif self.current_mode == GameMode.EXPERT:
            font.setPointSize(11)
            button_size = (32, 32)

        for h in range(self.height):
            for w in range(self.width):
                button = QPushButton()
                button.setFixedSize(button_size[0], button_size[1])
                button.setFont(font)
                button.meta = (h, w)
                button.mouseReleaseEvent = functools.partial(
                    self.on_mouse_release_event, button)
                button.mousePressEvent = functools.partial(
                    self.on_mouse_press_event, button)
                button.maybe_mine = False
                button.pressed = False
                button.paired_cell = self.minesweeper.field[h][w]
                self.gridLayout.addWidget(button, h, w)
                self.minesweeper.field[h][w].paired_button = button

        # resizing this way doesn't work.
        self.setFixedSize(self.sizeHint())
        QTimer.singleShot(0, lambda: self.setFixedSize(self.sizeHint()))
        # see: https://forum.qt.io/topic/4500/resize-top-level-window-to-fit-contents/4

    def on_mouse_press_event(self, button, ev):
        cell_visible = button.paired_cell.visible
        if not cell_visible and not button.maybe_mine and not button.pressed:
            # and ev.button() == PyQt5.QtCore.Qt.LeftButton:
            button.pressed = True
            button.setStyleSheet("border: 3px inset #aaa;")

    def on_mouse_release_event(self, button, ev):
        h, w = button.meta
        cell_visible = button.paired_cell.visible
        expected_amount_mines_in_area = button.paired_cell.amount.value

        if ev.button() == PyQt5.QtCore.Qt.LeftButton:
            if not cell_visible and not button.maybe_mine and button.pressed:
                button.pressed = False
                button.setStyleSheet("border: 0px")

                self.playsound(self.sound_click)

            if cell_visible and self.all_mines_in_area_marked(
                    expected_amount_mines_in_area, (h, w)):
                # todo: implement step_in_all_fields_area()

                self.step_in_neighbors((h, w))
            elif not button.maybe_mine:
                self.step_in(*button.meta)
        elif ev.button() == PyQt5.QtCore.Qt.RightButton:
            # ignore visible fields
            if not button.paired_cell.visible:
                if button.maybe_mine:
                    self.playsound(self.sound_no_flag)

                    button.setStyleSheet("")
                    button.setText("")
                    self.increment_mines_lcd()
                    button.maybe_mine = not button.maybe_mine
                else:
                    if self.decrement_mines_lcd():
                        self.playsound(self.sound_flag)

                        button.setStyleSheet(
                            "border: 1px solid black; background-color: #efefef;"
                        )
                        button.setText("🚩")
                        button.maybe_mine = not button.maybe_mine
                    else:
                        button.setStyleSheet("")
        ev.accept()

    def all_mines_in_area_marked(self, expected_amount_mines_in_area, pos):
        mines_in_area = self.minesweeper.on_neighbors(pos, lambda pos: None)
        print("marked:", mines_in_area)
        return mines_in_area == expected_amount_mines_in_area

    def step_in_neighbors(self, pos):
        # pass  # not implemented yet
        self.minesweeper.step_in_neighbors(pos)

    def increment_mines_lcd(self):
        value = self.lcdNumber_amount_mines.intValue()
        self.lcdNumber_amount_mines.display(value + 1)

    def decrement_mines_lcd(self):
        value = self.lcdNumber_amount_mines.intValue()

        if value > 0:
            self.lcdNumber_amount_mines.display(value - 1)
            return True
        else:
            return False

    def clear_layout(self, layout):
        while layout.count():
            child = layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()

    def start(self, initial_click_pos):
        self.start_game_timer()
        self.minesweeper.start(initial_click_pos)

    def reset(self):
        self.minesweeper = Game(self, self.height, self.width,
                                self.amount_mines)
        self.lcdNumber_amount_mines.display(self.amount_mines)
        self.initial_clicked = False
        self.initialise_field()
        self.enable_field()
        self.stop_game_timer()
        self.lcdNumber_playing_time.display(0)
        self.pushButton_reset.setText("😊")

    def step_in(self, h, w):
        try:
            if not self.initial_clicked:
                self.start((h, w))
                self.initial_clicked = True
            else:
                self.minesweeper.step_in(h, w)

            self.update_ui()
        except Exception as e:
            print(e)

    def update_ui(self):
        field = self.minesweeper.field

        for h in range(self.minesweeper.field_height):
            for w in range(self.minesweeper.field_width):
                if field[h][w].visible:
                    text = str(field[h][w].amount.value)

                    if text == "9":
                        text = "💣"
                    elif text == "0":
                        text = ""
                        field[h][w].paired_button.setStyleSheet(
                            "border: 1px solid #333")

                        # field[h][w].paired_button.setVisible(False)
                    else:
                        field[h][w].paired_button.setStyleSheet(
                            "border: 1px solid #333")

                    field[h][w].paired_button.setText(text)

        if self.minesweeper.won():
            if self.current_mode == GameMode.BEGINNER:
                self.playsound(self.sound_beginner_win)
            elif self.current_mode == GameMode.INTERMEDIATE:
                self.playsound(self.sound_intermediate_win)
            else:
                self.playsound(self.sound_expert_win)

            self.pushButton_reset.setText("😁")
            self.stop_game_timer()
            # self.show_message_box("Finished", "You WON!")
            self.disable_field()

    def game_over(self):
        self.playsound(self.sound_boom)
        self.pushButton_reset.setText("😵")
        self.stop_game_timer()
        # self.show_message_box("Finished", "GAME OVER :(")
        self.disable_field()

    def disable_field(self):
        for h in range(self.minesweeper.field_height):
            for w in range(self.minesweeper.field_width):
                self.minesweeper.field[h][w].paired_button.setEnabled(False)

    def enable_field(self):
        for h in range(self.minesweeper.field_height):
            for w in range(self.minesweeper.field_width):
                self.minesweeper.field[h][w].paired_button.setEnabled(True)

    def show_message_box(self, title, text):
        msg = QMessageBox(self)
        msg.setWindowTitle(title)
        msg.setText(text)
        msg.exec_()

    def open_twitch_support_page(self):
        self.playsound(self.sound_donate)
        webbrowser.open("https://streamlabs.com/tutorexilius")
Ejemplo n.º 22
0
class Controller:
    def __init__(self, view, log):
        self.log = log
        self.view = view
        self._player = QMediaPlayer()
        self._player.mediaStatusChanged.connect(self._player_status_changed)
        self._player.mediaChanged.connect(self._player_media_changed)
        self._player.currentMediaChanged.connect(self._player_current_media_changed)
        self._player.stateChanged.connect(self._player_state_changed)
        self._player.positionChanged.connect(self._player_position_changed)
        self._player.durationChanged.connect(self._player_duration_changed)
        self._searched_tracks = []
        self.playlists = []
        self.playing_playlist = 0
        self.last_colored_item = None

    def _player_status_changed(self, status):
        self.log.debug('_player_status_changed: %s', str(status))
        if status in [QMediaPlayer.EndOfMedia, QMediaPlayer.InvalidMedia]:
            self.next()

        if status in [QMediaPlayer.EndOfMedia, QMediaPlayer.NoMedia, QMediaPlayer.UnknownMediaStatus,
                      QMediaPlayer.InvalidMedia]:
            self.view.set_title()
        else:
            try:
                pos = self.playlists[self.playing_playlist].active_track
                if pos >= 0:
                    track = self.playlists[self.playing_playlist].tracks[pos]
                    self.view.set_title(track.title)
                self.update_list_position(pos)
            except IndexError:
                self.log.error('Index error in _player_status_changed')

    def _player_media_changed(self, media):
        self.log.debug('_player_media_changed: %s' % str(media))

    def _player_current_media_changed(self, media):
        self.log.debug('_player_current_media_changed: %s' % str(media))

    def _player_state_changed(self, state):
        self.log.debug('_player_state_changed: %s' % str(state))

    def _player_duration_changed(self, duration):
        self.log.debug('_player_duration_changed: %s' % str(duration))
        self.view.track_position.setMaximum(duration)

    def _player_position_changed(self, pos):
        self.view.track_position.setValue(pos)

    def volume_changed(self, value):
        self._player.setVolume(value)

    def update_status(self):
        total_duration = 0
        playlist_index = self.view.tabs.currentIndex()
        for track in self.playlists[playlist_index].tracks:
            total_duration += track.duration
        self.view.playlist_status.setText("%i tracks. Total duration %i:%02i:%02i:%02i" %
                                          (self.playlists[playlist_index].count(), total_duration // 86400,
                                           total_duration // 3600 % 24,
                                           total_duration // 60 % 60, total_duration % 60))

    def add_track(self, track, playlist_index=None):
        if playlist_index is None:
            playlist_index = self.view.tabs.currentIndex()
        self.playlists[playlist_index].add(track)
        self.view.tabs.widget(playlist_index).addItem(track.title)

    def remove_track(self, track_pos=None):
        if track_pos is None:
            track_pos = self.view.tabs.currentWidget().currentRow()
        if track_pos != -1:
            self.view.tabs.currentWidget().takeItem(track_pos)
            playlist_index = self.view.tabs.currentIndex()
            self.playlists[playlist_index].remove(track_pos)
            self.update_status()

    def remove_all_tracks(self):
        playlist_index = self.view.tabs.currentIndex()
        self.playlists[playlist_index].clear()
        self.view.tabs.currentWidget().clear()
        self.update_status()

    def next(self):
        self.log.debug('next')
        # if we close last tab with current track, after it ended, we stop playing
        # todo: need check, that if we close not last tab with current song, we also need stop after song ended
        if self.playing_playlist >= len(self.playlists):
            return
        next_pos = self.playlists[self.playing_playlist].get_next_track(shuffle=bool(self.view.shuffle.checkState()))
        if next_pos is not None:
            self.playlists[self.playing_playlist].active_track = next_pos
            url = self.playlists[self.playing_playlist].tracks[next_pos].stream_url()
            self._player.setMedia(QMediaContent(QUrl(url)))
            self.play()

    def previous(self):
        self.log.debug('previous')
        prev_pos = self.playlists[self.playing_playlist].get_prev_track(shuffle=bool(self.view.shuffle.checkState()))
        if prev_pos is not None:
            self.playlists[self.playing_playlist].active_track = prev_pos
            url = self.playlists[self.playing_playlist].tracks[prev_pos].stream_url()
            self._player.setMedia(QMediaContent(QUrl(url)))
            self.play()

    def play(self):
        self.log.debug('play')
        self._player.play()

    def pause(self):
        self.log.debug('pause')
        self._player.pause()

    def update_list_position(self, position):
        showed_list = self.view.tabs.currentWidget()
        if self.last_colored_item:
            self.last_colored_item.setBackground(QBrush())
        if (position >= 0) and (position <= showed_list.count()):
            self.last_colored_item = showed_list.item(position)
            self.last_colored_item.setBackground(QBrush(QColor('red')))

    def change_track(self):
        self.log.debug('change_track')
        playlist_index = self.view.tabs.currentIndex()
        self.playing_playlist = playlist_index
        position = self.view.tabs.currentWidget().currentRow()
        self.playlists[self.playing_playlist].active_track = position
        self.log.debug('position: %i' % position)
        url = self.playlists[self.playing_playlist].tracks[position].stream_url()
        self._player.setMedia(QMediaContent(QUrl(url)))
        if self._player.state() in [QMediaPlayer.StoppedState, QMediaPlayer.PausedState]:
            self.play()

    def change_track_position(self):
        self._player.setPosition(self.view.track_position.value())

    def remove_dublicates(self):
        selected_playlist = self.view.tabs.currentIndex()
        playlist = self.playlists[selected_playlist]
        processed_ids = []
        position_for_removing = []
        for index in range(len(playlist.tracks)):
            if playlist.tracks[index].id in processed_ids:
                position_for_removing.append(index)
            else:
                processed_ids.append(playlist.tracks[index].id)

        self.log.debug('tracks count: %i' % len(playlist.tracks))
        counter = 0
        for index in reversed(position_for_removing):
            self.log.debug('track index for removing: %i' % index)
            self.remove_track(track_pos=index)
            counter += 1
        self.log.info('Removed %i tracks.' % counter)

    def save_track(self, playlist_pos=None, track_pos=None):
        if track_pos is None:
            track_pos = self.view.tabs.currentWidget().currentRow()
        if playlist_pos is None:
            playlist_pos = self.view.tabs.currentIndex()
        playlist = self.playlists[playlist_pos]
        track = playlist.tracks[track_pos]
        track.save()

    def download_playlist(self):
        selected_playlist = self.view.tabs.currentIndex()
        playlist = self.playlists[selected_playlist]
        for track_pos in range(playlist.count()):
            self.log.info('Saving %i/%s track...' % (track_pos+1, playlist.count()))
            self.save_track(playlist_pos=selected_playlist, track_pos=track_pos)
        self.log.info('Saving done.')

    def load_playlist(self):
        playlist_index = self.view.tabs.currentIndex()
        playlist = self.playlists[playlist_index]
        loaded_playlist = sc_load_playlist(playlist.name)
        if not loaded_playlist:
            self.log.error('Playlist not exists.')
            return
        self.remove_all_tracks()
        for track in loaded_playlist:
            self.add_track(track)
        self.update_status()

    def save_playlist(self):
        playlist_index = self.view.tabs.currentIndex()
        playlist = self.playlists[playlist_index]
        sc_save_playlist(playlist.name, playlist)

    def add_playlist(self, name):
        self.playlists.append(Playlist(name))

    def remove_playlist(self, index):
        self.log.debug('remove playlist with index = %i' % index)
        del (self.playlists[index])

    def search_tracks(self):
        self.view.search_list.clear()
        tracks = sc_search_tracks(self.view.input.text())
        self._searched_tracks = tracks
        total_duration = 0
        for track in self._searched_tracks:
            self.view.search_list.addItem(track.title)
            total_duration += track.duration
        self.view.search_status.setText("Founded %i tracks. Total duration %i:%02i:%02i:%02i" %
                                        (len(self._searched_tracks),
                                         total_duration // 86400000, total_duration // 3600000 % 24,
                                         total_duration // 60000 % 60, total_duration // 1000 % 60))

    def search_similar(self):
        self.view.search_list.clear()
        position = self.view.tabs.currentWidget().currentRow()
        playlist_index = self.view.tabs.currentIndex()
        track = self.playlists[playlist_index].tracks[position]

        related_tracks = track.search_related()
        self._searched_tracks = related_tracks
        total_duration = 0
        for track in self._searched_tracks:
            self.view.search_list.addItem(track.title)
            total_duration += track.duration
        self.view.search_status.setText("Founded %i tracks. Total duration %i:%02i:%02i:%02i" %
                                        (len(self._searched_tracks),
                                         total_duration // 86400000, total_duration // 3600000 % 24,
                                         total_duration // 60000 % 60, total_duration // 1000 % 60))

    def clicked_add_track(self):
        position = self.view.search_list.currentRow()
        self.add_track(self._searched_tracks[position])

    def clicked_add_all_tracks(self):
        for row in range(self.view.search_list.count()):
            self.add_track(self._searched_tracks[row])

    def load_current_state(self):
        if not os.path.isfile('state.pickle'):
            return
        f = open('state.pickle', 'rb')
        state = pickle.load(f)
        f.close()
        loaded_playlists = state['playlists']
        self.log.debug('loaded %i playlists.' % len(loaded_playlists))
        for i in range(len(loaded_playlists) - len(self.playlists)):
            self.view.tab_add()
        self.playlists.clear()
        index = 0
        for playlist in loaded_playlists:
            self.log.debug('playlist: %s, len: %i' % (playlist.name, len(playlist.tracks)))
            self.add_playlist(playlist.name)
            for track in playlist.tracks:
                self.add_track(track, playlist_index=index)
            index += 1
        self.log.debug(len(self.playlists))
        self.log.debug('curent tab: %i' % state['current_playlist'])
        self.view.tabs.setCurrentIndex(state['current_playlist'])
        self.log.debug('volume: %i' % state['volume'])
        self.view.volume.setValue(state['volume'])
        self.view.shuffle.setCheckState(state['shuffle'])

    def save_current_state(self):
        state = dict()
        self.log.debug('playlists count: %i' % len(self.playlists))
        state['playlists'] = self.playlists
        state['current_playlist'] = self.view.tabs.currentIndex()
        state['volume'] = self.view.volume.value()
        state['shuffle'] = self.view.shuffle.checkState()
        f = open('state.pickle', 'wb')
        pickle.dump(state, f)
        f.close()
Ejemplo n.º 23
0
class videoPlayer(QWidget):  # 视频播放类
    def __init__(self, titleName):  # 构造函数
        super(videoPlayer, self).__init__()  # 类的继承

        self.length = 0  # 视频总时长
        self.position = 0  # 视频当前时长
        self.count = 0
        self.player_status = -1

        # 设置窗口
        self.setGeometry(300, 50, 1200, 800) #大小,与桌面放置位置
        self.setWindowIcon(QIcon(':/images/video_player_icon.png'))  # 程序图标
        self.setWindowTitle(titleName)  # 窗口名称
        self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)
     

        # 设置窗口背景
        self.palette = QPalette()  
        self.palette.setColor(QPalette.Background, Qt.black)
        self.setPalette(self.palette)

        self.now_position = QLabel("/  00:00")   # 目前时间进度
        self.all_duration = QLabel('00:00')   # 总的时间进度
        self.all_duration.setStyleSheet('''QLabel{color:#ffffff}''')
        self.now_position.setStyleSheet('''QLabel{color:#ffffff}''')

        #视频插件
        self.video_widget = QVideoWidget(self)
        self.video_widget.setGeometry(QRect(0, 0, 1200, 700)) #大小,与桌面放置位置
        #self.video_widget.resize(1200, 700)  # 设置插件宽度与高度
        #self.video_widget.move(0, 30)   # 设置插件放置位置
        self.video_palette = QPalette()
        self.video_palette.setColor(QPalette.Background, Qt.black)  # 设置播放器背景
        self.video_widget.setPalette(self.video_palette)
        video_widget_color="background-color:#000000"
        self.video_widget.setStyleSheet(video_widget_color)
        
     
        #布局容器
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setSpacing(0)
        #self.verticalLayout.setContentsMargins(0, 5, 0, 10)
        self.layout = QHBoxLayout()
        self.layout.setSpacing(15)   # 各个插件的间距
        
        
        
        # 设置播放器
        self.player = QMediaPlayer(self)   
        self.player.setVideoOutput(self.video_widget)
        #设置播放按钮事件
        self.player.durationChanged.connect(self.get_duration_func)
        self.player.positionChanged.connect(self.progress)  # 媒体播放时发出信号
        self.player.mediaStatusChanged.connect(self.playerStatusChanged)
        self.player.error.connect(self.player_error)
        

        # 播放按钮
        self.play_btn = QPushButton(self)
        self.play_btn.setIcon(QIcon(':/images/play_btn_icon.png'))  # 设置按钮图标,下同
        self.play_btn.setIconSize(QSize(35,35))
        self.play_btn.setStyleSheet('''QPushButton{border:none;}QPushButton:hover{border:none;border-radius:35px;}''')
        self.play_btn.setCursor(QCursor(Qt.PointingHandCursor))
        self.play_btn.setToolTip("播放")
        self.play_btn.setFlat(True)
        #self.play_btn.hide()
        #isHidden()      #判定控件是否隐藏

        #isVisible()     判定控件是否显示
        self.play_btn.clicked.connect(self.start_button)

        #音量条        
        self.volume_slider = QSlider(Qt.Horizontal)  # 声音设置
        self.volume_slider.setMinimum(0)    # 音量0到100
        self.volume_slider.setMaximum(100)
       
        self.volume_slider.valueChanged.connect(self.volumes_change)
      
        self.volume_slider.setStyleSheet('''QSlider{}
QSlider::sub-page:horizontal:disabled{background: #00009C;  border-color: #999;  }
QSlider::add-page:horizontal:disabled{background: #eee;  border-color: #999; }
QSlider::handle:horizontal:disabled{background: #eee;  border: 1px solid #aaa;  border-radius: 4px;  }
QSlider::add-page:horizontal{background: #575757;  border: 0px solid #777;  height: 10px;border-radius: 2px; }
QSlider::handle:horizontal:hover{background:qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0.6 #2A8BDA,   stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }
QSlider::sub-page:horizontal{background: qlineargradient(x1:0, y1:0, x2:0, y2:1,   stop:0 #B1B1B1, stop:1 #c4c4c4);  background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,stop: 0 #5DCCFF, stop: 1 #1874CD);  border: 1px solid #4A708B;  height: 10px;  border-radius: 2px;  }
QSlider::groove:horizontal{border: 1px solid #4A708B;  background: #C0C0C0;  height: 5px;  border-radius: 1px;  padding-left:-1px;  padding-right:-1px;}
QSlider::handle:horizontal{background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,   stop:0.6 #45ADED, stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }''')


        #视频播放进度条        
        self.video_slider = QSlider(Qt.Horizontal, self)  # 视频进度拖拖动
        self.video_slider.setMinimum(0)   # 视频进度0到100%
        #self.video_slider.setMaximum(100)
        self.video_slider.setSingleStep(1)
        self.video_slider.setGeometry(QRect(0, 0, 200, 10))
        self.video_slider.sliderReleased.connect(self.video_silder_released)
        self.video_slider.sliderPressed.connect(self.video_silder_pressed)
        
        self.video_slider.setStyleSheet('''QSlider{}
QSlider::sub-page:horizontal:disabled{background: #00009C;  border-color: #999;  }
QSlider::add-page:horizontal:disabled{background: #eee;  border-color: #999; }
QSlider::handle:horizontal:disabled{background: #eee;  border: 1px solid #aaa;  border-radius: 4px;  }
QSlider::add-page:horizontal{background: #575757;  border: 0px solid #777;  height: 10px;border-radius: 2px; }
QSlider::handle:horizontal:hover{background:qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0.6 #2A8BDA,   stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }
QSlider::sub-page:horizontal{background: qlineargradient(x1:0, y1:0, x2:0, y2:1,   stop:0 #B1B1B1, stop:1 #c4c4c4);  background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,stop: 0 #5DCCFF, stop: 1 #1874CD);  border: 1px solid #4A708B;  height: 10px;  border-radius: 2px;  }
QSlider::groove:horizontal{border: 1px solid #4A708B;  background: #C0C0C0;  height: 5px;  border-radius: 1px;  padding-left:-1px;  padding-right:-1px;}
QSlider::handle:horizontal{background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,   stop:0.6 #45ADED, stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }''')

     #静音按钮    
        self.mute_button = QPushButton('')
        self.mute_button.clicked.connect(self.mute)
        self.mute_button.setIconSize(QSize(30,30))
        self.mute_button.setStyleSheet('''QPushButton{border:none;}QPushButton:hover{border:none;}''')
        self.mute_button.setCursor(QCursor(Qt.PointingHandCursor))
        self.mute_button.setToolTip("播放")
        self.mute_button.setFlat(True)
        self.mute_button.setIcon(QIcon(':/images/sound_btn_icon.png'))
                            
        
        #暂停按钮
        self.pause_btn = QPushButton('')   
        self.pause_btn.setIcon(QIcon(':/images/stop_btn_icon.png'))
        self.pause_btn.clicked.connect(self.stop_button)
        self.pause_btn.setIconSize(QSize(35,35))
        self.pause_btn.setStyleSheet('''QPushButton{border:none;}QPushButton:hover{border:none;}''')
        self.pause_btn.setCursor(QCursor(Qt.PointingHandCursor))
        self.pause_btn.setToolTip("播放")
        self.pause_btn.setFlat(True)
        self.pause_btn.hide()
        

        #音量值和音量显示标签
        self.volume_value = QLabel()
        self.volume_value.setText(' ' * 5)
        self.volume_value.setStyleSheet('''QLabel{color:#ffffff;}''')

        self.volume_t = QLabel()
        
        self.volume_t.setStyleSheet('''QLabel{color:#ffffff;}''')

        #视频文件打开按钮
        self.open_btn = QPushButton('Open')
        self.open_btn.clicked.connect(self.getfile)

        #全屏按钮
        self.screen_btn = QPushButton('')
        self.screen_btn.setIcon(QIcon(QPixmap(':/images/fullsrceen_btn_icon.png')))
        self.screen_btn.setIconSize(QSize(38,38))
        self.screen_btn.setStyleSheet('''QPushButton{border:none;}QPushButton:hover{border:1px solid #F3F3F5;border-radius:35px;}''')
        self.screen_btn.setCursor(QCursor(Qt.PointingHandCursor))
        self.screen_btn.setToolTip("播放")
        self.screen_btn.setFlat(True)
        self.screen_btn.clicked.connect(self.fullscreen)

        #添加按钮组件
        self.verticalLayout.addStretch()
        self.layout.addWidget(self.play_btn, 0, Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.pause_btn, 0, Qt.AlignCenter | Qt.AlignVCenter)  # 插件,与前一个模块的距离,位置
        
        self.layout.addWidget(self.all_duration,0, Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.now_position, 0, Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.video_slider, 15, Qt.AlignVCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.mute_button , 0, Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.volume_slider, 0, Qt.AlignCenter | Qt.AlignVCenter)
    
        self.layout.addWidget(self.volume_value, 0, Qt.AlignCenter | Qt.AlignVCenter)
       
        #self.layout.addWidget(self.screen_btn)
        #self.layout.addWidget(self.open_btn)
        self.verticalLayout.addLayout(self.layout)
        
        #self.verticalLayout.addLayout(self.layout)
        self.setLayout(self.verticalLayout)


    def player_error(self, errorCode):
        print('error = ' + str(errorCode))
        try:
            if errorCode == 0:
                pass
            elif errorCode == 1:
                self.showAlertWindow('errorCode:1 \n\n无效视频源。')
            elif errorCode == 2:
                self.showAlertWindow('errorCode:2 \n\n不支持的媒体格式')
            elif errorCode == 3:
                self.showAlertWindow('errorCode:3 \n\n网络错误')
            elif errorCode == 4:
                self.showAlertWindow('errorCode:4 \n\n没有权限播放该视频')
            elif errorCode == 5:
                self.showAlertWindow('errorCode:5 \n\n视频服务不存在,无法继续播放。')
            else:
                self.showAlertWindow('未知错误')
        except:
            self.showAlertWindow('视频加载异常')
        
        
    def video_silder_pressed(self):
        if self.player.state != 0:
            self.player.pause()
            
        
    
    def playerStatusChanged(self, status):
        self.player_status = status
        if status == 7:
            self.play_btn.show()
            self.pause_btn.hide()
            
        #print('playerStatusChanged =' + str(status) + '...............')

    def resizeEvent(self, e):
        #print(e.size().width(), e.size().height())
        newSize = e.size()
        self.video_widget.setGeometry(0, 0, newSize.width(), newSize.height() - 50)
        #self.video_widget.setGeometry(0, 0, 0, 0)
        
        
        
    def closeEvent(self, e):
        self.player.stop()
       
    def get_duration_func(self, d):
        try:
            end_number = int(d / 1000 / 10) + 1
            #print('end_number = ' + str(end_number))
            sum = 0
            for n  in range (1,end_number):
                sum = sum + n

            vv = int((100 / (d / 1000)) * (d / 1000))
            self.video_slider.setMaximum(d)
            #self.video_slider.setMaximum(vv + sum)
            #print(100 + sum)

            all_second = int(d / 1000 % 60)  # 视频播放时间
            all_minute = int(d / 1000 / 60)
           
           
            if all_minute < 10:
                
                if all_second < 10:
                    
                    self.all_duration.setText('0' + str(all_minute) + ':0' + str(all_second))
                else:
                    
                    self.all_duration.setText('0' + str(all_minute) + ':' + str(all_second))
            else:
                
                if all_second < 10:
                    
                    self.all_duration.setText(str(all_minute) + ':0' + str(all_second))
                else:
                    
                    self.all_duration.setText(str(all_minute) + ':' + str(all_second))
        except Exception as e:
            pass
        
        
        
    def mouseDoubleClickEvent(self, e):
        try:
            
            #print('mouseDoubleClickEvent................... = ' + str(self.player.state()))
            if self.player.state() == 2:
                #视频暂停
                self.player.play()
                self.play_btn.hide()
                self.pause_btn.show()
        
            elif self.player.state() == 1:
                # 正在播放
                self.player.pause()
                self.play_btn.show()
                self.pause_btn.hide()
            else:
                #视频停止
                self.play_btn.hide()
                self.pause_btn.show()
                self.player.setPosition(0)
                self.video_slider.setValue(0)
                self.player.play()
        except Exception as e:
            pass
        
            
    
    def start_button(self):   # 视频播放按钮
        try:
            
            self.play_btn.hide()
            self.pause_btn.show()
        
            if self.player_status == 7:
                self.video_slider.setValue(0)
                self.player.setPosition(0)
            
            self.player.play()
        except Exception as e:
            pass
            
        

    def stop_button(self):       # 视频暂停按钮
        self.play_btn.show()
        self.pause_btn.hide()
        self.player.pause()

    def getfile(self, filepath):       # 打开视频文件
        try:
            
            #print(str(filepath))
            url = QUrl.fromLocalFile(filepath)
            if url.isValid():
                self.player.setMedia(QMediaContent(url))  # 返回该文件地址,并把地址放入播放内容中
                self.player.setVolume(50)  # 设置默认打开音量即为音量条大小
                self.volume_value.setText(str(50))
                self.volume_slider.setValue(50)
            else:
                self.showAlertWindow('视频地址无效')
                
        except Exception as e:
            self.showAlertWindow()
        

        
    def clearVolumeValue():
        self.volume_value.setText(' ' * 5)
        
    
    def volumes_change(self):    # 拖动进度条设置声音
        try:
            size = self.volume_slider.value()
            if size:
                # 但进度条的值不为0时,此时音量不为静音,音量值即为进度条值
                self.player.setMuted(False)
                self.player.setVolume(size)
                volume_value = str(size) + ' ' * 4
                self.volume_value.setText(volume_value)
                #print(size)
                self.mute_button.setIcon(QIcon(':/images/sound_btn_icon.png'))
            else:
                self.player.setMuted(True)
                self.mute_button.setIcon(QIcon(':/images/mute_btn_icon.png'))
                self.player.setVolume(0)
                volume_value = '0' + ' ' * 4
                self.volume_value.setText(volume_value)

            if len(str(size)) == 1:
                volume_value = str(size) + ' ' * 4
            elif len(str(size)) == 2:
                volume_value = str(size)+ ' ' * 3
            else:
                volume_value = str(size) + ' ' * 2
                
            self.volume_value.setText(volume_value)
        except Exception as e:
            pass
        

    def mute(self):
        try:
            if self.player.isMuted():
                self.mute_button.setIcon(QIcon(':/images/sound_btn_icon.png'))
                self.player.setMuted(False)
                self.volume_slider.setValue(50)
                volume_value = '50' + ' ' * 4
                self.volume_value.setText(volume_value)
            else:
                self.mute_button.setIcon(QIcon(':/images/mute_btn_icon.png'))
                self.player.setMuted(True)  # 若不为静音,则设置为静音,音量置为0
                self.volume_slider.setValue(0)
                volume_value = '0' + ' ' * 4
                self.volume_value.setText(volume_value)
        except Exception as e:
            pass
        

    def progress(self):  # 视频进度条自动释放与播放时间
        
        try:
            
            self.length = self.player.duration() + 1
            self.position = self.player.position()
            #print(str(self.length) + ':' + str(self.position))
            self.count += 1

            video_silder_maximum = self.video_slider.maximum()
           
            #video_silder_value = int(((video_silder_maximum / (self.length / 1000)) * (self.position / 1000)))

            #self.video_slider.setValue(video_silder_value + self.count)

            self.video_slider.setValue(self.position)
           
            #print('video_slider_value = ' + str(video_silder_value + self.count))
           
            now_second = int(self.position / 1000 % 60)
            now_minute = int(self.position / 1000 / 60)
           
            #print(str(now_minute) + ':' + str(now_second))
            if now_minute < 10:
                if now_second < 10:
                   
                    self.now_position.setText('/  0' + str(now_minute) + ':0' + str(now_second))
                else:
                    
                   
                    self.now_position.setText('/  0' + str(now_minute) + ':' + str(now_second))
            else:
                
                #print('now_minute < 10' + str(now_minute) + ':' + str(now_second))
               
                if now_second < 10:
                    #print('now_second < 10' + str(now_minute) + ':' + str(now_second))
                    #self.now_position.setText(str(now_minute) + ':0' + str(now_second))
                    self.now_position.setText('/  ' + str(now_minute) + ':0' + str(now_second))
                else:
                    #print('now_second > 10' + str(now_minute) + ':' + str(now_second))
                    self.now_position.setText('/  ' + str(now_minute) + ':' + str(now_second))
        except Exception as e:
            pass
       
               
            
       
    def video_silder_released(self):  # 释放滑条时,改变视频播放进度
        try:
            
            #print('video_silder_released......')
            if self.player.state() != 0:
                self.player.setPosition(self.video_slider.value())
                self.player.play()
            else: #如果视频是停止状态,则拖动进度条无效
                self.video_slider.setValue(0) 
        except Exception as e:
            pass
        

    def fullscreen(self):
        self.showFullScreen()
        

    def keyPressEvent(self, event):  # 重新改写按键
        if event.key() == Qt.Key_Escape:
            self.winquit()

    def winquit(self):  # 退出窗口
        self.showNormal()

    def showAlertWindow(self, msg = '视频加载出错!'):
        reply = QMessageBox.information(self,
                                    "消息框标题",  
                                    msg,  
                                    QMessageBox.Yes)

    def setWindowTitleName(self, titleName):
        self.setWindowTitle(titleName)  # 窗口名称
Ejemplo n.º 24
0
class VideoPlayer(QWidget):
    def __init__(self, parent=None, mute=True):
        QWidget.__init__(self, parent)

        self.ui = Ui_VideoPlayer()

        self.error_handler = lambda txt: None

        savecwd = os.getcwd()
        os.chdir('view/ui')
        self.ui.setupUi(self)
        os.chdir(savecwd)

        self.ui.bn_size.hide()

        self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        # self.item=QGraphicsVideoItem()
        # self.ui.mid_frame_grid_layout.addItem(self.item,0,0)
        # self.media_player.setVideoOutput(self.item)

        self.media_player_widget = QVideoWidget(self.ui.mid_frame)
        self.ui.mid_frame_grid_layout.addWidget(self.media_player_widget, 0, 0)
        self.media_player.setVideoOutput(self.media_player_widget)

        # self.media_player.stateChanged.connect(self.state_changed)
        self.media_player.bufferStatusChanged.connect(
            self.buffer_status_changed)
        self.media_player.mediaStatusChanged.connect(self.media_status_changed)
        self.media_player.positionChanged.connect(self.positionChanged)
        self.media_player.durationChanged.connect(self.durationChanged)
        self.media_player.error.connect(self.handleError)
        # self.media_player.metaDataChanged.connect(self.meta_data_changed)

        self.ui.bn_mute.setChecked(mute)
        self.mute()
        self.connect_to_playlist(connected=False, toggle_playlist=lambda: None)
        self.ui.dial_volume.setFixedWidth(50)

        # binding
        self.ui.bn_play.clicked.connect(self.media_player.play)
        self.ui.bn_pause.clicked.connect(self.media_player.pause)
        self.ui.bn_mute.clicked.connect(self.mute)
        self.ui.bn_stop.clicked.connect(self.media_player.stop)
        self.ui.bn_next.clicked.connect(self.next)
        self.ui.bn_prev.clicked.connect(self.prev)
        self.ui.bn_playlist.clicked.connect(self.show_playlist)
        self.ui.bn_uget.clicked.connect(self.on_uget_pressed)

        self.ui.progress_slider.sliderMoved.connect(
            self.media_player.setPosition)
        # self.ui.spin_volume.valueChanged.connect(self.media_player.setVolume)
        self.ui.dial_volume.valueChanged.connect(self.media_player.setVolume)

        self.url = ''
        self.altermate = list()
        self.duration = '0:00'
        self.change_position = None
        self.uget_handler = lambda fname='', url='': None
        # self.on_end_of_playing=lambda :None

    def set_error_handler(self, handler):
        self.error_handler = handler

    def icons_set(self, bn, fname_off, fname_on=None):
        icon = QIcon()
        icon.addPixmap(QPixmap(fname_off), QIcon.Normal, QIcon.Off)
        if fname_on is not None:
            icon.addPixmap(QPixmap(fname_on), QIcon.Normal, QIcon.On)
        bn.setIcon(icon)

    def connect_to_playlist(self,
                            connected=False,
                            goto_prev=lambda: None,
                            goto_next=lambda: None,
                            toggle_playlist=None):
        self.goto_next = goto_next
        self.goto_prev = goto_prev
        if toggle_playlist is not None:
            self.toggle_playlist = toggle_playlist
        self.connected = connected

        if self.connected:
            self.ui.playlist_frame.show()
            self.ui.bn_add.hide()
            self.ui.bn_minus.show()
        else:
            self.ui.playlist_frame.hide()
            self.ui.bn_add.show()
            self.ui.bn_minus.hide()

    def set_plus_handler(self, handler=lambda: None):
        self.ui.bn_add.clicked.connect(handler)

    def set_minus_handler(self, handler=lambda: None):
        self.ui.bn_minus.clicked.connect(handler)

    def set_uget_handler(self, handler=lambda fname='', url='': None):
        self.uget_handler = handler

    def on_uget_pressed(self, url=None):
        self.uget_handler(fname=urlparse(
            url.rstrip('/'))[2].rpartition('/')[2],
                          url=url)

    def set_url(self, url=''):
        self.url = url
        self.altermate = list()
        self.ui.bn_size.hide()
        self.media_player.setMedia(QMediaContent(QUrl(url)))
        uget_menu = QMenu(self)
        uget_menu_action = QAction('Standart quality',
                                   self,
                                   triggered=self.get_handler(
                                       self.on_uget_pressed, url))
        uget_menu.addAction(uget_menu_action)
        self.ui.bn_uget.setMenu(uget_menu)

    def change_url(self, url):
        position = self.media_player.position()
        self.media_player.stop()
        self.media_player.setMedia(QMediaContent(QUrl(url)))
        self.media_player.play()
        self.change_position = position

    def add_alternate_url(self, caption='', url=''):
        self.ui.bn_size.show()
        self.altermate.append(dict(caption=caption, url=url))
        menu = QMenu(self)
        uget_menu = QMenu(self)
        for item in self.altermate:
            menu_action = QAction(item['caption'],
                                  self,
                                  triggered=self.get_handler(
                                      self.change_url, item['url']))
            menu.addAction(menu_action)
            uget_menu_action = QAction(item['caption'],
                                       self,
                                       triggered=self.get_handler(
                                           self.on_uget_pressed, item['url']))
            uget_menu.addAction(uget_menu_action)
        self.ui.bn_size.setMenu(menu)
        self.ui.bn_uget.setMenu(uget_menu)

    def get_handler(self, function, arg):
        return lambda: function(arg)

    def play(self):
        self.media_player.play()

    def pause(self):
        self.media_player.pause()

    def stop(self):
        self.media_player.stop()

    def next(self):
        self.goto_next()

    def prev(self):
        self.goto_prev()

    def show_playlist(self):
        self.toggle_playlist()

    def mute(self):
        if self.ui.bn_mute.isChecked():
            self.media_player.setMuted(True)
        else:
            self.media_player.setMuted(False)
            self.media_player.setVolume(self.ui.dial_volume.value())

    def little_forvard(self, s=30):
        self.media_player.setPosition(self.media_player.position() + s * 1000)

    def media_status_changed(self, status):
        # print('Media status=', status)

        if status == QMediaPlayer.StalledMedia:
            self.ui.progress_buffer.show()
        else:
            self.ui.progress_buffer.hide()

        if status == QMediaPlayer.BufferedMedia:
            if self.change_position is not None:
                # print('Changing position')
                self.media_player.setPosition(self.change_position)
                self.change_position = None
        if status == QMediaPlayer.EndOfMedia:
            self.goto_next()

    def buffer_status_changed(self, status):
        # print('Buffer status=', status)
        self.ui.progress_buffer.setValue(status)

    # def state_changed(self,status):
    #     print('State=', status)

    def state(self):
        return self.media_player.state()

    def positionChanged(self, position):
        self.ui.progress_slider.setValue(position)
        self.ui.lbl_time.setText(
            self.time_format(position) + ' / ' + self.duration)

    def durationChanged(self, duration):
        self.ui.progress_slider.setRange(0, duration)
        self.duration = self.time_format(duration)

    def time_format(self, ms):
        dur = ms // 1000
        minutes = dur // 60
        secundes = dur - minutes * 60
        return '%d:%02d' % (minutes, secundes)

    def handleError(self):
        print("Error in " + self.url + ': ' + self.media_player.errorString())
        self.error_handler('Player error: ' + self.media_player.errorString())
Ejemplo n.º 25
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()
Ejemplo n.º 26
0
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():
#         currentIndex = 0
#     playlist.setCurrentIndex((currentIndex))
#     player.play()

btn = QPushButton("play", clicked = play)
btn.show()
class VideoPlayer(QWidget):
    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAcceptDrops(True)
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback)
        self.mediaPlayer.mediaStatusChanged.connect(self.printMediaData)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)

        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setFixedWidth(70)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))
        self.lbl.selectionChanged.connect(lambda: self.lbl.setSelection(0, 0))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setFixedWidth(70)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))
        self.elbl.selectionChanged.connect(
            lambda: self.elbl.setSelection(0, 0))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        self.clip = QApplication.clipboard()
        self.process = QProcess(self)
        self.process.readyRead.connect(self.dataReady)
        self.process.finished.connect(self.playFromURL)

        self.myurl = ""

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(5, 0, 5, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \
                "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \
                "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes"

        self.widescreen = True

        #### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)

        self.shortcut = QShortcut(QKeySequence("y"), self)
        self.shortcut.activated.connect(self.getYTUrl)

        self.shortcut = QShortcut(QKeySequence("o"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(" "), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence("f"), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(
            QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left),
                                  self)
        self.shortcut.activated.connect(self.backSlider10)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        print("QT5 Player started")
        print("press 'o' to open file (see context menu for more)")
        self.suspend_screensaver()

    def mouseDoubleClickEvent(self, event):
        self.handleFullscreen()

    def playFromURL(self):
        self.mediaPlayer.pause()
        self.myurl = self.clip.text()
        self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(self.myurl)

    def getYTUrl(self):
        cmd = "youtube-dl -g -f best " + self.clip.text()
        print("grabbing YouTube URL")
        self.process.start(cmd)

    def dataReady(self):
        self.myurl = str(self.process.readAll(), encoding='utf8').rstrip()  ###
        self.myurl = self.myurl.partition("\n")[0]
        print(self.myurl)
        self.clip.setText(self.myurl)
        self.playFromURL()

    def suspend_screensaver(self):
        'suspend linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false',
            shell=True)
        proc.wait()

    def resume_screensaver(self):
        'resume linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled true',
            shell=True)
        proc.wait()

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "Open Movie",
            QDir.homePath() + "/Videos",
            "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)"
        )

        if fileName != '':
            self.loadFilm(fileName)
            print("File loaded")

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(mtime.toString())

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: ", self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        self.resume_screensaver()
        print("Goodbye ...")
        app.quit()

    def contextMenuRequested(self, point):
        menu = QMenu()
        actionFile = menu.addAction(QIcon.fromTheme("video-x-generic"),
                                    "open File (o)")
        actionclipboard = menu.addSeparator()
        actionURL = menu.addAction(QIcon.fromTheme("browser"),
                                   "URL from Clipboard (u)")
        actionclipboard = menu.addSeparator()
        actionYTurl = menu.addAction(QIcon.fromTheme("youtube"),
                                     "URL from YouTube (y)")
        actionclipboard = menu.addSeparator()
        actionToggle = menu.addAction(QIcon.fromTheme("next"),
                                      "show / hide Slider (s)")
        actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"),
                                    "Fullscreen (f)")
        action169 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "16 : 9")
        action43 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "4 : 3")
        actionSep = menu.addSeparator()
        actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "Info (i)")
        action5 = menu.addSeparator()
        actionQuit = menu.addAction(QIcon.fromTheme("application-exit"),
                                    "Exit (q)")

        actionFile.triggered.connect(self.openFile)
        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        actionYTurl.triggered.connect(self.getYTUrl)
        action169.triggered.connect(self.screen169)
        action43.triggered.connect(self.screen43)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             round((mwidth + mscale) / 1.778))
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             round((mwidth + mscale) / 1.33))
        #elif self.positionSlider.hasFocus():
        #    self.positionSlider.value = self.positionSlider.value + 5

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio))

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio))

    def handleFullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.showNormal()
            print("no Fullscreen")
        else:
            self.showFullScreen()
            QApplication.setOverrideCursor(Qt.BlankCursor)
            print("Fullscreen entered")

    def handleInfo(self):
        msg = QMessageBox.about(self, "QT5 Player", self.myinfo)

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.778))
        else:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33))

    def showSlider(self):
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.55))
        else:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33))

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def mousePressEvent(self, evt):
        self.oldPos = evt.globalPos()

    def mouseMoveEvent(self, evt):
        delta = QPoint(evt.globalPos() - self.oldPos)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = evt.globalPos()

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        elif event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        print("drop")
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            ### YouTube url
            if "youtube" in mydrop:
                print("is YouTube", mydrop)
                self.clip.setText(mydrop)
                self.getYTUrl()
            else:
                ### normal url
                print("generic url = ", mydrop)
                self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop)))
                self.playButton.setEnabled(True)
                self.mediaPlayer.play()
                self.hideSlider()

    def loadFilm(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()

    def printMediaData(self):
        if self.mediaPlayer.mediaStatus() == 6:
            if self.mediaPlayer.isMetaDataAvailable():
                res = str(self.mediaPlayer.metaData("Resolution")).partition(
                    "PyQt5.QtCore.QSize(")[2].replace(", ",
                                                      "x").replace(")", "")
                print("%s%s" % ("Video Resolution = ", res))
                if int(res.partition("x")[0]) / int(
                        res.partition("x")[2]) < 1.5:
                    self.screen43()
                else:
                    self.screen169()
            else:
                print("no metaData available")

    def openFileAtStart(self, filelist):
        matching = [s for s in filelist if ".myformat" in s]
        if len(matching) > 0:
            self.loadFilm(matching)
Ejemplo n.º 28
0
class Translater(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Translater, self).__init__(parent)
        self.setupUi(self)
        self.version = 2.8
        self.version_detail = '\n更新说明:\t增加字体、颜色设置;\n\t增加4种语言发音;\n\t优化语音播放代码。'
        self.cwd = os.path.expanduser('~')
        self.con_in_voice.hide()
        self.label_9.show()
        self.con_out_voice.hide()
        self.label_H.show()
        self.data_dict = {
            'version': self.version,
            'input': '',
            'data_info': [],
            'language': '',
            'output': [],
            'in_color': '#000000',
            'in_font': ['Arial', 9, False, False, False],
            'out_color': '#000000',
            'out_font': ['Arial', 9, False, False, False]
        }
        self.set_info()

        f = Faker(locale='zh-CN')
        self.ua_all = f.user_agent()
        self.button_fy.clicked.connect(self.tran_act)
        self.button_clear.clicked.connect(self.clearact)
        self.actionverson.triggered.connect(self.versionact)
        self.actionhelp.triggered.connect(self.helpact)
        self.con_in_color.clicked.connect(lambda: self.change_coloract(1))
        self.con_in_size.clicked.connect(lambda: self.change_fontact(1))
        self.con_out_color.clicked.connect(lambda: self.change_coloract(0))
        self.con_out_size.clicked.connect(lambda: self.change_fontact(0))
        self.con_in_voice.clicked.connect(lambda: self.speak_act(1))
        self.con_out_voice.clicked.connect(lambda: self.speak_act(0))

        self.player = QMediaPlayer()

    def set_info(self):
        if os.path.isfile(self.cwd + '/trandata.json'):
            with open(self.cwd + '/trandata.json', 'r',
                      encoding='utf-8') as fp:
                self.data_dict = json.load(fp)
            if 'version' not in self.data_dict.keys():
                os.remove(self.cwd + '/trandata.json')
                self.data_dict['version'] = self.version
            else:
                if self.data_dict['version'] != self.version:
                    os.remove(self.cwd + '/trandata.json')
                    self.data_dict['version'] = self.version
                l = self.data_dict['language']
                self.set_language(l)
                in_font = self.data_dict['in_font']
                self.set_fontact(in_font, 1)
                out_font = self.data_dict['out_font']
                self.set_fontact(out_font, 0)
                in_color = self.data_dict['in_color']
                self.con_in.setStyleSheet('color:' + in_color)
                out_color = self.data_dict['out_color']
                self.con_out.setStyleSheet('color:' + out_color)

    def change_fontact(self, sxt):
        font_font, b = QFontDialog.getFont()
        if b:
            font_f = font_font.family()
            font_s = font_font.pointSize()
            font_b = font_font.bold()
            font_i = font_font.italic()
            font_u = font_font.underline()
            font_x = [font_f, font_s, font_b, font_i, font_u]
            if sxt == 1:
                self.con_in.setFont(font_font)
                self.data_dict['in_font'] = font_x
            else:
                self.con_out.setFont(font_font)
                self.data_dict['out_font'] = font_x

    def set_fontact(self, font, sxt):
        set_font = QFont()
        set_font.setFamily(font[0])
        set_font.setPointSize(font[1])
        set_font.setBold(font[2])
        set_font.setItalic(font[3])
        set_font.setUnderline(font[4])
        if sxt == 1:
            self.con_in.setFont(set_font)
        else:
            self.con_out.setFont(set_font)

    def change_coloract(self, sxt):
        color_color = QColorDialog.getColor()
        get_color = color_color.name()
        if sxt == 1:
            self.con_in.setStyleSheet('color:' + get_color)
            self.data_dict['in_color'] = get_color
        else:
            self.con_out.setStyleSheet('color:' + get_color)
            self.data_dict['out_color'] = get_color

    def get_info(self, context):
        ua = ''.join(self.ua_all.split('/')[1:])
        m = hashlib.md5()
        m.update(ua.encode('utf-8'))
        bv = m.hexdigest()
        ts = str(int(time.time() * 1000))
        salt = ts + str(random.randint(0, 9))
        sign_str = 'fanyideskweb' + context + salt + 'Nw(nmmbP%A-r6U3EUn]Aj'
        mm = hashlib.md5()
        mm.update(sign_str.encode('utf-8'))
        sign = mm.hexdigest()
        self.data_dict['data_info'] = [bv, ts, salt, sign]
        return bv, ts, salt, sign

    def get_language(self):
        if self.radio_en.isChecked():
            language = 'en'
            self.con_in_voice.show()
            self.label_9.hide()
            self.con_out_voice.show()
            self.label_H.hide()
        if self.radio_ja.isChecked():
            language = 'ja'
            self.con_in_voice.show()
            self.label_9.hide()
            self.con_out_voice.show()
            self.label_H.hide()
        if self.radio_ko.isChecked():
            language = 'ko'
            self.con_in_voice.show()
            self.label_9.hide()
            self.con_out_voice.show()
            self.label_H.hide()
        if self.radio_ru.isChecked():
            language = 'ru'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_de.isChecked():
            language = 'de'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_fr.isChecked():
            language = 'fr'
            self.con_in_voice.show()
            self.label_9.hide()
            self.con_out_voice.show()
            self.label_H.hide()
        if self.radio_es.isChecked():
            language = 'es'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_pt.isChecked():
            language = 'pt'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_it.isChecked():
            language = 'it'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_ar.isChecked():
            language = 'ar'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_id.isChecked():
            language = 'id'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        if self.radio_vi.isChecked():
            language = 'vi'
            self.con_in_voice.hide()
            self.label_9.show()
            self.con_out_voice.hide()
            self.label_H.show()
        self.data_dict['language'] = language
        return language

    def set_language(self, l):
        if l == 'en':
            self.radio_en.setChecked(True)
        if l == 'ja':
            self.radio_ja.setChecked(True)
        if l == 'ko':
            self.radio_ko.setChecked(True)
        if l == 'ru':
            self.radio_ru.setChecked(True)
        if l == 'de':
            self.radio_de.setChecked(True)
        if l == 'fr':
            self.radio_fr.setChecked(True)
        if l == 'es':
            self.radio_es.setChecked(True)
        if l == 'pt':
            self.radio_pt.setChecked(True)
        if l == 'it':
            self.radio_it.setChecked(True)
        if l == 'ar':
            self.radio_ar.setChecked(True)
        if l == 'id':
            self.radio_id.setChecked(True)
        if l == 'vi':
            self.radio_vi.setChecked(True)

    def check_chinese(self, context):
        li = [
            '–', '—', '‘', '’', '“', '”', '…', '、', '。', '〈', '〉', '《', '》',
            '「', '」', '『', '』', '【', '】', '〔', '〕', '!', '(', ')', ',', '.',
            ':', ';', '?', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*',
            '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[',
            ']', '^', '_', '`', '{', '|', '}', '~', '\n'
        ]
        for ch in context:
            if ch in li:
                pass
            elif ch < u'\u4E00' or ch > u'\u9FA5':
                return False
        return True

    def tran(self, context):
        bv, ts, salt, sign = self.get_info(context)
        l = self.get_language()
        headers = {
            'User-Agent':
            self.ua_all,
            'Referer':
            'http://fanyi.youdao.com/',
            'Cookie':
            '[email protected]; JSESSIONID=aaaCotdaKLvMH7QRFDoix; OUTFOX_SEARCH_USER_ID_NCOO=51303853.7527974; ___rl__test__cookies='
            + ts
        }
        data = {
            'i': context,
            'client': 'fanyideskweb',
            'salt': salt,
            'sign': sign,
            'ts': ts,
            'bv': bv,
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'lan-select',
        }
        if self.check_chinese(context):
            data['from'] = 'zh-CHS'
            data['to'] = l
            self.con_in_voice.hide()
            self.label_9.show()
        else:
            data['from'] = l
            data['to'] = 'zh-CHS'
            self.con_out_voice.hide()
            self.label_H.show()

        url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
        response = post(url, data=data, headers=headers)
        data_dict = json.loads(response.text)
        data_dict_con = data_dict['translateResult']
        self.result = []
        for p in data_dict_con:
            for s in p:
                out_content = s['tgt']
                self.result.append(out_content)
        self.data_dict['output'] = self.result
        return self.result

    def get_speak(self):
        if self.radio_en.isChecked():
            speak = 'eng'
        elif self.radio_ja.isChecked():
            speak = 'jap'
        elif self.radio_ko.isChecked():
            speak = 'ko'
        elif self.radio_fr.isChecked():
            speak = 'fr'
        else:
            speak = 'eng'
            QMessageBox.warning(self, '错误', '不支持该语种发音,尝试采用英文发音。',
                                QMessageBox.Ok)
            self.radio_en.setChecked(True)
        return speak

    def speak_act(self, x):
        if x == 1:
            content = self.con_in.toPlainText()
        else:
            content = self.con_out.toPlainText()
        url = 'http://tts.youdao.com/fanyivoice'
        le = self.get_speak()
        voice_url = url + '?word=' + content + '&le=' + le
        self.player.setMedia(QMediaContent(QUrl(voice_url)))
        self.player.setVolume(50)
        self.player.play()
        self.player.stateChanged.connect(self.play_state)
        if x == 1:
            self.con_in_voice.setDisabled(True)
        else:
            self.con_out_voice.setDisabled(True)

    def play_state(self):
        self.con_in_voice.setEnabled(True)
        self.con_out_voice.setEnabled(True)

    def tran_act(self):
        '''
        翻译
        '''
        context = self.con_in.toPlainText()
        if context != '':
            self.data_dict['input'] = context
            try:
                temp = self.tran(context)
                self.con_out.clear()
                for i in temp:
                    self.con_out.appendPlainText(i)
                    self.con_out.repaint()
            except:
                self.con_out.setPlainText('引擎错误!请检查网络链接!')
        else:
            self.con_out.setPlainText('请先输入原文!')

    def closeEvent(self, event):
        with open(self.cwd + '/trandata.json', 'w', encoding='utf-8') as f:
            f.write(json.dumps(self.data_dict, ensure_ascii=False, indent=4))

    def clearact(self):
        self.con_in.clear()
        self.con_out.clear()

    def versionact(self):
        '''
        版本菜单
        '''
        QMessageBox.about(self, '版本',
                          '版本:V' + str(self.version) + self.version_detail)

    def helpact(self):
        '''
        帮助菜单
        '''
        QMessageBox.about(
            self, '帮助',
            '系统默认选择英文\n翻译后所选语种将被记录,作为下次翻译的默认语种。\n支持中文对多种语言、外文对中文的翻译\n系统自动判断用户输入语言是否为中文。\n非中文的原文,暂不支持自动判断语种。\n如需相应的外文翻译中文,请首先选择正确的外文语种。'
        )
Ejemplo n.º 29
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)
Ejemplo n.º 30
0
class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer() # 播放器
        self.playlist = QMediaPlaylist() # 播放列表
        self.title = '音乐播放器'
        self.volumeHint = QLabel('音量: 99%')
        self.mInfo = {
            'cover': './default_cover.jpg', 
            'music': '', 
            'singer': '',
            'duration': 0
        }
        self.aboutWin = AboutWindow()
        self.cover = QLabel()
        self.listWid = QListWidget()

        # 设置主窗口位置
        self.left = 200
        self.top = 100
        self.width = 500
        self.height = 430

        self.font = QFont('SansSerif', 10.5)
        self.color = 1  # 0 - 黑色界面, 1 - 白色界面
        self.userAction = 0  # 0 - 停止中, 1 - 播放中 2 - 暂停中
        self.initUI()

    def initUI(self):
        # 添加文件菜单
        menubar = self.menuBar()
        menubar.setNativeMenuBar(False) # 不使用本地菜单栏以获得全平台统一的效果
        filemenu = menubar.addMenu('文件')
        windowmenu = menubar.addMenu('窗口')

        fileAct = QAction('打开文件', self)
        folderAct = QAction('打开文件夹', self)
        themeAct = QAction('切换[亮/暗]主题', self)
        aboutAct = QAction('关于', self)

        fileAct.setShortcut('Ctrl+O')
        folderAct.setShortcut('Ctrl+D')
        themeAct.setShortcut('Ctrl+T')
        aboutAct.setShortcut('Ctrl+H')

        filemenu.addAction(fileAct)
        filemenu.addAction(folderAct)
        windowmenu.addAction(themeAct)
        windowmenu.addAction(aboutAct)

        fileAct.triggered.connect(self.openFile)
        folderAct.triggered.connect(self.addFiles)
        themeAct.triggered.connect(self.toggleColors)
        aboutAct.triggered.connect(self.viewAbout)
        self.listWid.itemDoubleClicked.connect(self.quickplayhandler)

        self.listWid.setFont(self.font)
        self.playlist.setPlaybackMode(2)
        self.setLayout()
        self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) # 禁用窗口最大化按钮
        self.setFont(self.font)
        self.setWindowTitle(self.title)
        self.setWindowIcon(QIcon('icon.ico'))
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setFixedSize(self.width, self.height)
        self.toggleColors()
        self.show()

    def setLayout(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)

        # 添加音量控制
        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(100)

        # 添加歌曲播放控制
        playBtn = QPushButton('播放')  # 播放
        pauseBtn = QPushButton('暂停')  # 暂停
        stopBtn = QPushButton('清空列表')  # 停止
        prevBtn = QPushButton('上一首') # 上一首
        playback = QComboBox() # 回放模式
        nextBtn = QPushButton('下一首') # 下一首

        playback.addItem('      单曲播放')
        playback.addItem('      单曲循环')
        playback.addItem('      列表播放')
        playback.addItem('      列表循环')
        playback.addItem('      列表随机')

        playback.setCurrentIndex(2)

        # 添加封面
        jpg = QPixmap(self.mInfo['cover']).scaled(300, 300)
        self.cover.setPixmap(jpg)

        # 添加布局
        Area = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        showLayout = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()

        # 歌曲播放控制布局
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)

        # 播放列表控制布局
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(playback)
        playlistCtrlLayout.addWidget(nextBtn)

        # 显示布局
        showLayout.addWidget(self.cover)
        showLayout.addWidget(self.listWid)

        # 竖直排列
        Area.addStretch(1)
        Area.addLayout(showLayout)
        Area.addWidget(self.volumeHint)
        Area.addWidget(volumeslider)
        Area.addLayout(controls)
        Area.addLayout(playlistCtrlLayout)
        wid.setLayout(Area)

        # 事件绑定
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)
        playback.currentIndexChanged.connect(self.playbackhandler)
        stopBtn.clicked.connect(self.stophandler)

        prevBtn.clicked.connect(self.prevSong)
        nextBtn.clicked.connect(self.nextSong)

        self.statusBar().showMessage('文件-打开文件(夹)-选择-开始播放')
        self.playlist.currentMediaChanged.connect(self.songChanged)

    def openFile(self):
        print("点击了文件按钮")
        song = QFileDialog.getOpenFileName(self, "打开音频", "github-lkxed", "音频文件 (*.mp3 *.ogg *.wav *.m4a)")

        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
                self.listWid.addItem(song[0].split('/')[-1].split('.')[0])
                print(self.playlist.mediaCount())
            else:
                self.playlist.addMedia(QMediaContent(url))
                print(self.playlist.mediaCount())

    def addFiles(self):
        print("点击了文件夹按钮")
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
            print(self.playlist.mediaCount())
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            print(self.playlist.mediaCount())
            self.userAction = 1
    
    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, '打开音频文件夹', '.')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    print(it.filePath(), fInfo.suffix())
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        print('added file', fInfo.fileName())
                        self.listWid.addItem(fInfo.fileName())
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                print(it.filePath(), fInfo.suffix())
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    print('added file', fInfo.fileName())
                    self.listWid.addItem(fInfo.fileName())
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))

            # 设置ListItem高度
            for x in range(self.listWid.count()):
                self.listWid.item(x).setSizeHint(QSize(100, 30))

    # 处理双击播放事件
    def quickplayhandler(self, item):
        # 若播放列表没有音频了就跳出打开文件对话框
        if self.playlist.mediaCount() == 0:
            self.openFile()
        # 若播放列表不为空则播放
        elif self.playlist.mediaCount() != 0:
            index = self.listWid.currentRow()
            self.player.playlist().setCurrentIndex(index)
            self.player.play()
            self.userAction = 1

    # 处理按钮播放事件
    def playhandler(self):
        if self.userAction == 2:
            self.player.play()
        elif self.userAction == 0:
            # 若播放列表没有音频了就跳出打开文件对话框
            if self.playlist.mediaCount() == 0:
                self.openFile()
            # 若播放列表不为空则播放
            elif self.playlist.mediaCount() != 0:
                index = self.listWid.currentRow()
                self.player.playlist().setCurrentIndex(index)
                self.player.play()
                self.userAction = 1
        else:
            self.statusBar().showMessage('已经在播放中!')

    # 处理暂停事件
    def pausehandler(self):
        self.userAction = 2
        self.player.pause()

    # 处理清空列表事件
    def stophandler(self):
        self.userAction = 0
        self.player.stop()
        self.playlist.clear()
        self.listWid.clear()
        self.mInfo['cover'] = 'default_cover.jpg'
        jpg = QPixmap(self.mInfo['cover']).scaled(300, 300)
        self.cover.setPixmap(jpg)
        print("Playlist cleared!")
        self.statusBar().showMessage("列表已清空")

    def changeVolume(self, value):
        text = '音量: ' + str(value) + '%'
        self.volumeHint.setText(text)
        self.player.setVolume(value)

    # 上一首事件
    def prevSong(self):
        if self.playlist.currentIndex() == 0:
            self.playlist.setCurrentIndex(self.playlist.mediaCount()-1)
        else:
            self.player.playlist().previous()
    
    # 随机播放事件
    def playbackhandler(self, index):
        self.playlist.setPlaybackMode(index)
        print(self.playlist.playbackMode())

    # 下一首事件
    def nextSong(self):
        if self.playlist.mediaCount() == self.playlist.currentIndex()+1:
            self.playlist.setCurrentIndex(0)
        else:
            self.player.playlist().next()
    
    # 音频切换事件
    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            self.showInfo(url)
            self.statusBar().showMessage(url.fileName())
            index = self.player.playlist().currentIndex()
            self.listWid.setCurrentRow(index)

    def showInfo(self, url):
        filepath = url.path()[1:]
        filename = url.fileName()[:-4]
        print(filename)
        if filepath[-3:] == 'm4a':
            file = mutagen.MP4(filepath)
            try:
                img = file.tags['covr'][0]
                self.mInfo['cover'] = './cover/'+filename+'.jpg'
                if not os.path.exists('./cover'):
                    os.mkdir('./cover')
                if not os.path.exists(self.mInfo['cover']):
                    with open(self.mInfo['cover'], 'wb') as f:
                        f.write(img)
            except:
                print('找不到封面')
                self.mInfo['cover'] = './default_cover.jpg'

        elif filepath[-3:] == 'mp3':
            file = mutagen.File(filepath)
            try:
                img = file.tags['APIC:'].data
                self.mInfo['cover'] = './cover/'+filename+'.jpg'
                if not os.path.exists('./cover'):
                    os.mkdir('./cover')
                if not os.path.exists(self.mInfo['cover']):
                    with open(self.mInfo['cover'], 'wb') as f:
                        f.write(img)
            except:
                print('找不到封面')
                self.mInfo['cover'] = './default_cover.jpg'
        else:
            print('音频文件不支持提取封面')
            self.mInfo['cover'] = './default_cover.jpg'

        jpg = QPixmap(self.mInfo['cover']).scaled(300, 300)
        self.cover.setPixmap(jpg)


    # 主题切换事件
    def toggleColors(self):

        app.setStyle("Fusion")
        palette = QPalette()

        # 明亮主题
        if self.color == 0:
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(25, 25, 25))
            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.Link, QColor(235, 101, 54))
            palette.setColor(QPalette.Highlight, QColor(235, 101, 54))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 1

        # 黑暗主题
        elif self.color == 1:
            palette.setColor(QPalette.Window, Qt.white)
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, QColor(240, 240, 240))
            palette.setColor(QPalette.AlternateBase, Qt.white)
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, Qt.white)
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(66, 155, 248))
            palette.setColor(QPalette.Highlight, QColor(66, 155, 248))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 0

    def viewAbout(self):
        self.aboutWin.show()
Ejemplo n.º 31
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()
Ejemplo n.º 32
0
class Player(QMediaPlayer):
    def __init__(self, parent=None):
        super(Player, self).__init__(parent)
        self.parent = parent
        self.player = QMediaPlayer()
        self.queueList = QMediaPlaylist()
        self.player.setPlaylist(self.queueList)
        self.queueData = []
        self.position = 0
        self.volume = 100
        self.status = 0  # 0: stop, 1: playing/paused

        self.player.mediaStatusChanged.connect(self.qmp_mediaStatusChanged)
        self.player.positionChanged.connect(self.qmp_positionChanged)
        self.player.durationChanged.connect(self.durationChanged)
        self.queueList.currentIndexChanged.connect(self.playlistPosChanged)

    def add(self, data):
        """Add track to the queue"""
        queueData = {
            'pc_title': data['pc_title'],
            'title': data['title'],
            'url': data['url'],
            'date': data['date_format'],
            'description': data['description']
        }
        self.queueData.append(queueData)
        self.queueList.addMedia(QMediaContent(QUrl(data['url'])))

    def playPause(self):
        icon = QIcon.fromTheme("media-playback-pause")

        if self.player.state() == QMediaPlayer.StoppedState:
            if self.player.mediaStatus() == QMediaPlayer.NoMedia:
                if self.queueList.mediaCount() != 0:
                    self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia:
                self.queueList.setCurrentIndex(self.position)
                self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia:
                self.player.play()
        elif self.player.state() == QMediaPlayer.PlayingState:
            icon = QIcon.fromTheme("media-playback-start")
            self.player.pause()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.play()

        self.parent.playBtn.setIcon(icon)

    def startPlay(self):
        data = self.queueData[0]
        self.queueList.setCurrentIndex(0)
        self.parent.curPCLabel.setText(data['pc_title'])
        self.parent.curTrackName.setText(data['title'])
        self.playstatus = 1
        self.player.play()
        icon = QIcon.fromTheme("media-playback-pause")
        self.parent.playBtn.setIcon(icon)

    def stop(self):
        self.player.stop()
        icon = QIcon.fromTheme("media-playback-start")
        self.parent.playBtn.setIcon(icon)

    def setPosition(self, pos):
        self.player.setPosition(pos)

    def durationChanged(self, duration):
        total_time = '0:00:00'
        duration = self.player.duration()
        total_time = ms_to_time(duration)
        self.parent.timeSlider.setMaximum(duration)
        self.currentTrackDuration = duration
        self.parent.totalTimeLabel.setText(total_time)

    def qmp_mediaStatusChanged(self, status):
        icon = QIcon.fromTheme("media-playback-pause")
        if self.player.state() == QMediaPlayer.StoppedState:
            icon = QIcon.fromTheme("media-playback-start")
        elif self.player.state() == QMediaPlayer.PausedState:
            icon = QIcon.fromTheme("media-playback-start")

        self.parent.playBtn.setIcon(icon)

    def qmp_positionChanged(self, position, senderType=False):
        self.currentTime = position
        current_time = '0:00:00'

        if position != -1:
            current_time = ms_to_time(position)
            self.parent.timeLabel.setText(current_time)

        self.parent.timeSlider.blockSignals(True)
        self.parent.timeSlider.setValue(position)
        self.parent.timeSlider.blockSignals(False)

    def playlistPosChanged(self):
        pos = self.queueList.currentIndex()
        data = self.queueData[pos]
        self.parent.curPCLabel.setText(data['pc_title'])
        self.parent.curTrackName.setText(data['title'])
        windowTitle = '{0} - {1}'.format(data['pc_title'], data['title'])
        self.parent.setWindowTitle(windowTitle)
        if self.queueList.mediaCount() > 1:
            if pos < self.queueList.mediaCount():
                self.parent.queueNextBtn.setEnabled(True)
            else:
                self.parent.queueNextBtn.setEnabled(False)

            if pos > 0:
                self.parent.queuePrevBtn.setEnabled(True)
            else:
                self.parent.queuePrevBtn.setEnabled(False)

            if pos < self.queueList.mediaCount():
                prevPos = 0
                if self.position < pos:
                    prevPos = pos - 1
                else:
                    prevPos = pos + 1
                prevItem = self.parent.queueList.item(prevPos)
                prevWidget = self.parent.queueList.itemWidget(prevItem)
                if prevItem:
                    prevWidget.statusIcon.setPixmap(QPixmap())

        self.position = pos
        item = self.parent.queueList.item(pos)
        widget = self.parent.queueList.itemWidget(item)
        icon = QIcon.fromTheme("media-playback-start")
        widget.statusIcon.setPixmap(icon.pixmap(16, 16))

    def setVolume(self, volume):
        self.player.setVolume(volume)

    def rev10Secs(self):
        position = self.player.position()
        new_pos = position - 10000
        self.player.setPosition(new_pos)

    def for10Secs(self):
        position = self.player.position()
        new_pos = position + 10000
        self.player.setPosition(new_pos)

    def delete(self, position):
        """ Delete the track and her data from position"""
        self.queueData.pop(position)
        self.queueList.removeMedia(position)
        if (position == self.position):
            self.playlistPosChanged()
Ejemplo n.º 33
0
class VentanaFinal(QWidget):
    def __init__(self, ancho, alto, volumen, ruta_fiesta, ruta_smoke,
                 ruta_victoria, ruta_derrota):
        # Definición de atributos
        super().__init__()

        self.tamano = (ancho, alto)
        self.setFixedSize(*self.tamano)

        self.volumen = volumen
        self.init_gui(ruta_fiesta, ruta_smoke, ruta_victoria, ruta_derrota)

    def init_gui(self, ruta_fiesta, ruta_smoke, ruta_victoria, ruta_derrota):
        # Reproductor de musica
        url_victoria = QUrl.fromLocalFile(ruta_victoria)
        self.kumbia = QMediaContent(url_victoria)
        url_derrota = QUrl.fromLocalFile(ruta_derrota)
        self.flauta_sad = QMediaContent(url_derrota)
        self.reproductor = QMediaPlayer()
        self.reproductor.setVolume(self.volumen)

        # Letras
        letra1 = QFont()
        letra1.setFamily("Agency FB")
        letra1.setPointSize(70)
        letra1.setBold(True)
        letra2 = QFont()
        letra2.setFamily("Agency FB")
        letra2.setPointSize(75)
        letra2.setBold(True)

        # Gifs
        self.label_gif = QLabel('', self)
        self.gif_fiesta = QMovie(ruta_fiesta)
        self.gif_smoke = QMovie(ruta_smoke)

        # Texto
        self.label_borde = QLabel('', self)
        self.label_borde.setFont(letra2)
        self.label_texto = QLabel('', self)
        self.label_texto.setFont(letra1)

    def actualizar_pantalla(self, gif, texto, musica):
        # Setea el gif, texto y musica correspondiente a la ventana.
        self.label_gif.setMovie(gif)
        gif.setScaledSize(QSize(*self.tamano))
        self.label_gif.resize(*self.tamano)
        self.reproductor.setMedia(musica)
        self.label_texto.setText(texto)
        self.label_texto.resize(self.label_texto.sizeHint())
        self.label_borde.setText(texto)
        self.label_borde.resize(self.label_borde.sizeHint())

    def mostrar_final(self, victoria):
        # Realiza cambios especificos a las situaciones de victoria o derrota a la ventana.
        # Son diferencias puramente esteticas.
        # Comienza la reproducion del GIF y la musica y muestra la ventana.
        if victoria:
            self.actualizar_pantalla(self.gif_fiesta, 'YOU WIN', self.kumbia)
            self.label_borde.setStyleSheet('color: rgb(255, 225, 225);')
            self.label_texto.setStyleSheet('color: rgb(255, 51, 102);')
            self.label_texto.move(
                (self.width() - self.label_texto.width()) // 2, 30)
            self.label_borde.move(
                (self.width() - self.label_borde.width()) // 2, 30)
            self.gif_fiesta.start()
        else:
            self.actualizar_pantalla(self.gif_smoke, 'YOU LOSE',
                                     self.flauta_sad)
            self.label_borde.setStyleSheet('color: rgb(0, 0, 0);')
            self.label_texto.setStyleSheet('color: rgb(255, 225, 225);')
            self.label_texto.move(
                (self.width() - self.label_texto.width()) // 2,
                self.height() - 150)
            self.label_borde.move(
                (self.width() - self.label_borde.width()) // 2,
                self.height() - 150)
            self.gif_smoke.start()
        self.reproductor.play()
        self.show()
Ejemplo n.º 34
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        ##      self.setWindowTitle("Demo10_1,音乐播放器")
        self.player = QMediaPlayer(self)
        self.playlist = QMediaPlaylist(self)
        self.player.setPlaylist(self.playlist)
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)  #循环模式

        self.__duration = ""  #文件总时间长度
        self.__curPos = ""  #当前播放到位置

        self.player.stateChanged.connect(self.do_stateChanged)

        self.player.positionChanged.connect(self.do_positionChanged)

        self.player.durationChanged.connect(self.do_durationChanged)

        self.playlist.currentIndexChanged.connect(self.do_currentChanged)

##  ==============自定义功能函数============

##  ===============event 处理函数==========

    def closeEvent(self, event):  ##窗体关闭时
        ##  窗口关闭时不能自动停止播放,需手动停止
        if (self.player.state() == QMediaPlayer.PlayingState):
            self.player.stop()

##  ==========由connectSlotsByName() 自动连接的槽函数==================
#  播放列表管理

    @pyqtSlot()  ##添加文件
    def on_btnAdd_clicked(self):
        ##      curPath=os.getcwd()     #获取系统当前目录
        ##      curPath=QDir.homePath()
        curPath = QDir.currentPath()
        dlgTitle = "选择音频文件"
        filt = "音频文件(*.mp3 *.wav *.wma);;所有文件(*.*)"
        fileList, flt = QFileDialog.getOpenFileNames(self, dlgTitle, curPath,
                                                     filt)
        count = len(fileList)
        if count < 1:
            return

        filename = fileList[0]
        fileInfo = QFileInfo(filename)  #文件信息
        QDir.setCurrent(fileInfo.absolutePath())  #重设当前路径

        for i in range(count):
            filename = fileList[i]
            fileInfo.setFile(filename)
            song = QMediaContent(QUrl.fromLocalFile(filename))
            self.playlist.addMedia(song)  #添加播放媒体
            ##         basename=os.path.basename(filename)    #文件名和后缀
            basename = fileInfo.baseName()
            self.ui.listWidget.addItem(basename)  #添加到界面文件列表

        if (self.player.state() != QMediaPlayer.PlayingState):
            self.playlist.setCurrentIndex(0)
            self.player.play()

    @pyqtSlot()  ##移除一个文件
    def on_btnRemove_clicked(self):
        pos = self.ui.listWidget.currentRow()
        item = self.ui.listWidget.takeItem(pos)  #python会自动删除

        if (self.playlist.currentIndex() == pos):  #是当前播放的曲目
            nextPos = 0
            if pos >= 1:
                nextPos = pos - 1

            self.playlist.removeMedia(pos)  #从播放列表里移除
            if self.ui.listWidget.count() > 0:  #剩余个数
                self.playlist.setCurrentIndex(nextPos)
                self.do_currentChanged(nextPos)  #当前曲目变化
            else:
                self.player.stop()
                self.ui.LabCurMedia.setText("无曲目")
        else:
            self.playlist.removeMedia(pos)

    @pyqtSlot()  ##清空播放列表
    def on_btnClear_clicked(self):
        self.playlist.clear()  #清空播放列表
        self.ui.listWidget.clear()
        self.player.stop()  #停止播放

    ##   @pyqtSlot()    ##双击时切换播放文件
    def on_listWidget_doubleClicked(self, index):
        rowNo = index.row()  #行号
        self.playlist.setCurrentIndex(rowNo)
        self.player.play()

#  播放控制

    @pyqtSlot()  ##播放
    def on_btnPlay_clicked(self):
        if (self.playlist.currentIndex() < 0):
            self.playlist.setCurrentIndex(0)
        self.player.play()

    @pyqtSlot()  ##暂停
    def on_btnPause_clicked(self):
        self.player.pause()

    @pyqtSlot()  ##停止
    def on_btnStop_clicked(self):
        self.player.stop()

    @pyqtSlot()  ##上一曲目
    def on_btnPrevious_clicked(self):
        self.playlist.previous()

    @pyqtSlot()  ##下一曲目
    def on_btnNext_clicked(self):
        self.playlist.next()

    @pyqtSlot()  ##静音控制
    def on_btnSound_clicked(self):
        mute = self.player.isMuted()
        self.player.setMuted(not mute)
        if mute:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/volumn.bmp"))
        else:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/mute.bmp"))

    @pyqtSlot(int)  ##调节音量
    def on_sliderVolumn_valueChanged(self, value):
        self.player.setVolume(value)

    @pyqtSlot(int)  ##文件进度调控
    def on_sliderPosition_valueChanged(self, value):
        self.player.setPosition(value)

##  =============自定义槽函数===============================

    def do_stateChanged(self, state):  ##播放器状态变化
        self.ui.btnPlay.setEnabled(state != QMediaPlayer.PlayingState)
        self.ui.btnPause.setEnabled(state == QMediaPlayer.PlayingState)
        self.ui.btnStop.setEnabled(state == QMediaPlayer.PlayingState)

    def do_positionChanged(self, position):  ##当前文件播放位置变化,更新进度显示
        if (self.ui.sliderPosition.isSliderDown()):  #在拖动滑块调整进度
            return
        self.ui.sliderPosition.setSliderPosition(position)
        secs = position / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__curPos = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

    def do_durationChanged(self, duration):  ##文件时长变化
        self.ui.sliderPosition.setMaximum(duration)

        secs = duration / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__duration = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

    def do_currentChanged(self, position):  ##playlist当前曲目变化
        self.ui.listWidget.setCurrentRow(position)
        item = self.ui.listWidget.currentItem()  #QListWidgetItem
        if (item != None):
            self.ui.LabCurMedia.setText(item.text())
Ejemplo n.º 35
0
class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.title = 'Personal audio player v2.3'
        self.left = 300
        self.top = 300
        self.width = 300
        self.height = 150
        self.color = 0  # 0- toggle to dark 1- toggle to light
        self.userAction = -1  # 0- stopped, 1- playing 2-paused
        self.duration = 0
        #self.getRecommendedPlaylist()
        self.initUI()

    def initUI(self):
        # Add file menu
        menubar = self.menuBar()
        filemenu = menubar.addMenu('File')
        windowmenu = menubar.addMenu('Window')
        connectTo = menubar.addMenu('Connect to...')

        fileAct = QAction('Open File', self)
        folderAct = QAction('Open Folder', self)
        themeAct = QAction('Toggle light/dark theme', self)
        yandexMusic = QAction('Yandex Music', self)
        deezer = QAction('Deezer', self)
        spotify = QAction('Spotify', self)
        pandora = QAction('Pandora', self)
        mixcloud = QAction('Pandora', self)

        fileAct.setShortcut('Ctrl+O')
        folderAct.setShortcut('Ctrl+D')
        themeAct.setShortcut('Ctrl+T')


        filemenu.addAction(fileAct)
        filemenu.addAction(folderAct)
        windowmenu.addAction(themeAct)
        connectTo.addAction(yandexMusic)
        connectTo.addAction(deezer)
        connectTo.addAction(pandora)
        connectTo.addAction(mixcloud)
        connectTo.addAction(spotify)

        fileAct.triggered.connect(self.openFile)
        folderAct.triggered.connect(self.addFiles)
        themeAct.triggered.connect(self.toggleColors)
        yandexMusic.triggered.connect(self.connectYandexMusic)
        deezer.triggered.connect(self.connectYandexMusic)
        pandora.triggered.connect(self.connectYandexMusic)
        mixcloud.triggered.connect(self.connectYandexMusic)
        spotify.triggered.connect(self.connectYandexMusic)

        self.addControls()

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.toggleColors()
        self.show()

    def downloadTrack(self, name):
        page = requests.get("http://zaycev.net/search.html?query_search=" + name).text
        parser = fromstring(page)
        fileJSON = parser.xpath('//div/@data-url')
        resp = requests.get("http://zaycev.net" + fileJSON[1])
        data = resp.json()
        with open("track.json", 'w') as outfile:
            json.dump(data, outfile)
        connection_file = open("track.json", 'r')
        conn_string = json.load(connection_file)

        track = requests.get(conn_string['url'].rsplit('?')[0])
        try:
            os.makedirs('./tracks')
        except OSError:
            pass

        out = open("./tracks/" + name.strip() + ".mp3", 'wb')
        out.write(track.content)
        out.close()
        QMessageBox.about(self, "Track added!", name.strip() + " was added")

    def playRecommend(self):
        try:
            similarTracks = open("playlist.txt", 'r')
            i = 0
            for line in similarTracks.readlines():
                if i == 5:
                    break
                else:
                    i = i+1
                print(line)
                self.downloadTrack(line)
                self.openFileRec("./tracks/" + line.strip() + ".mp3")

        except:
            QMessageBox.about(self, "Play error!", "Unknown error!")

    def getRecommendedPlaylist(self, song):
        try:
            audio = ID3(song[0])
            title = ''.join(audio['TIT2'].text[0].rsplit('(')[0])
            if title[-1] == ' ':
                title = title[0:-1]
            artist = audio['TPE1'].text[0]
            if artist[-1] == ' ':
                artist = artist[0:-1]
            print(artist + " " + title)
            resp = requests.get("http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=" + artist + "&track=" + title +
                                "&api_key=API_key&format=json")
            data = resp.json()
            with open("playlist" + artist + "-" + title + ".json", 'w') as outfile:
                json.dump(data, outfile)
            connection_file = open("playlist" + artist + "-" + title + ".json", 'r')
            conn_string = json.load(connection_file)

            with open("playlist.txt", 'a') as playlistFile:
                for track in conn_string['similartracks']['track']:
                    playlistFile.write(track['artist']['name'] + " " + track['name'] + "\n")
            playlistFile.close()
        except:
            QMessageBox.about(self, "Error!", "Some trouble with export title or artist name, try other track")

    def getRecommendedPlaylistFolder(self, song):
        audio = ID3(song)
        title = ''.join(audio['TIT2'].text[0].rsplit('(')[0])
        if title[-1] == ' ':
            title = title[0:-1]
        artist = audio['TPE1'].text[0]
        if artist[-1] == ' ':
            artist = artist[0:-1]
        print(artist + " " + title)
        resp = requests.get("http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=" + artist + "&track=" + title +
                            "&api_key=API_key&format=json")
        data = resp.json()
        with open("playlist" + artist + "-" + title + ".json", 'w') as outfile:
            json.dump(data, outfile)
            connection_file = open("playlist" + artist + "-" + title + ".json", 'r')
        conn_string = json.load(connection_file)
        with open("playlist.txt", 'a') as playlistFile:
            for track in conn_string['similartracks']['track']:
                playlistFile.write(track['artist']['name'] + " " + track['name'] + "\n")
        playlistFile.close()

    def addControls(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)
        # Add song controls
        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(50)

        sldPosition = QSlider(Qt.Horizontal, self)
        sldPosition.setMinimum(0)
        sldPosition.setFocusPolicy(Qt.NoFocus)
        #sldPosition.valueChanged.connect(self.player.setPosition)
        self.player.positionChanged.connect(sldPosition.setValue)
        sldPosition.setMaximum(180000)

        playBtn = QPushButton('Play')  # play button
        pauseBtn = QPushButton('Pause')  # pause button
        stopBtn = QPushButton('Stop')  # stop button
        # Add playlist controls
        prevBtn = QPushButton('Prev')
        shuffleBtn = QPushButton('Shuffle')
        nextBtn = QPushButton('Next')
        playRecommendedBtn = QPushButton('Play Recommended Playlist')
        like = QPushButton('Like')
        dislike = QPushButton('DisLike')

        # Add button layouts
        controlArea = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()
        playRec = QHBoxLayout()
        ld = QHBoxLayout()

        # Add buttons to song controls layout
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)
        # Add buttons to playlist controls layout
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(shuffleBtn)
        playlistCtrlLayout.addWidget(nextBtn)
        playRec.addWidget(playRecommendedBtn)
        ld.addWidget(like)
        ld.addWidget(dislike)
        # Add to vertical layout
        controlArea.addWidget(sldPosition)
        controlArea.addWidget(volumeslider)
        controlArea.addLayout(controls)
        controlArea.addLayout(playlistCtrlLayout)
        controlArea.addLayout(playRec)
        controlArea.addLayout(ld)
        wid.setLayout(controlArea)
        # Connect each signal to their appropriate function
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)
        stopBtn.clicked.connect(self.stophandler)

        prevBtn.clicked.connect(self.prevSong)
        shuffleBtn.clicked.connect(self.shufflelist)
        nextBtn.clicked.connect(self.nextSong)

        playRecommendedBtn.clicked.connect(self.playRecommend)

        like.clicked.connect(self.like)
        dislike.clicked.connect(self.dislike)

        self.statusBar()

        self.playlist.currentMediaChanged.connect(self.songChanged)

    def like(self, text):
        QMessageBox.about(self, "Attention!", "You have Liked track!")

    def dislike(self, text):
        QMessageBox.about(self, "Attention!", "You have DisLiked track!")

    def connectYandexMusic(self):
        apple = LoginWindow()
        apple.exec_()

    def openFile(self):
        print("File button clicked!")
        song = QFileDialog.getOpenFileName(self, "Open Song", "~", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")
        print(song[0])

        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
                print(self.playlist.mediaCount())
            else:
                self.playlist.addMedia(QMediaContent(url))
                print(self.playlist.mediaCount())
            self.getRecommendedPlaylist(song)

    def openFileRec(self, path):
        song = path

        if song != '':
            url = QUrl.fromLocalFile(song)
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
                print(self.playlist.mediaCount())
            else:
                self.playlist.addMedia(QMediaContent(url))
                print(self.playlist.mediaCount())

    def addFiles(self):
        print("Folder button clicked!")
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
            print(self.playlist.mediaCount())
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            print(self.playlist.mediaCount())
            self.userAction = 1

    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, 'Open Music Folder', '~')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    print(it.filePath(), fInfo.suffix())
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        print('added file', fInfo.fileName())
                        self.getRecommendedPlaylistFolder(it.filePath())
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                print(it.filePath(), fInfo.suffix())
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    print('added file', fInfo.fileName())
                    self.getRecommendedPlaylistFolder(it.filePath())
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))

    def playhandler(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.play()
            print(self.playlist.mediaCount())
            self.userAction = 1

    def pausehandler(self):
        self.userAction = 2
        self.player.pause()

    def stophandler(self):
        self.userAction = 0
        self.player.stop()
        self.playlist.clear()
        print("Playlist cleared!")
        self.statusBar().showMessage("Stopped and cleared playlist")

    def changeVolume(self, value):
        self.player.setVolume(value)

    def changePosition(self, value):
        self.player.setPosition(value)

    def prevSong(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().previous()

    def shufflelist(self):
        self.playlist.shuffle()
        print("Shuffled playlist!")

    def nextSong(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().next()

    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            self.statusBar().showMessage(url.fileName())

    def toggleColors(self):

        app.setStyle("Fusion")
        palette = QPalette()
        if self.color == 0:
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(25, 25, 25))
            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.Link, QColor(235, 101, 54))
            palette.setColor(QPalette.Highlight, QColor(235, 101, 54))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 1
        elif self.color == 1:
            palette.setColor(QPalette.Window, Qt.white)
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, QColor(240, 240, 240))
            palette.setColor(QPalette.AlternateBase, Qt.white)
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, Qt.white)
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(66, 155, 248))
            palette.setColor(QPalette.Highlight, QColor(66, 155, 248))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 0
Ejemplo n.º 36
0
class Control:
    """A class that handles the logic behind the program by manipulating the GUI classes
    and calling their methods in response to received signals."""

    MAGIC = b"\x01\xff"

    def __init__(self, screens: list) -> None:
        self.player = QMediaPlayer()
        self.player.setAudioRole(QAudio.MusicRole)
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)
        self.mainWindow = MainWindow(self, screens)
        self.mainArea = self.mainWindow.centralWidget().upperBox.mainArea
        self.songList = self.mainWindow.centralWidget().upperBox.songList
        self.mediaControlArea = self.mainWindow.centralWidget(
        ).mediaControlArea
        self.mainWindow.show()
        self.library = None
        self.currentSong = None
        self.playing = False
        self.random = False
        self.repeat = 0
        self.volume = 50

        self.volumeChange(self.volume)
        self.mediaControlArea.volumeControl.setValue(self.volume)

        self.mainTimer = QTimer()
        self.mainTimer.setInterval(100)
        self.mainTimer.timeout.connect(self.updateSongProgress)
        self.mainTimer.start()

        self.libraryUpdateTimer = QTimer()
        self.libraryUpdateTimer.setInterval(15_000)
        self.libraryUpdateTimer.timeout.connect(self.updateLibrary)
        self.libraryUpdateTimer.start()

        self._connection = None
        self.connections()

        self.displayedType = None
        self.displayedName = None
        self.types = None
        self.songListWidth = None
        values = self.load()
        if values:
            self.mainWindow.setGeometry(*values)
            self.volumeChange(self.volume)
            self.mediaControlArea.volumeControl.setValue(self.volume)

        self.setUpTimer = QTimer()
        self.setUpTimer.setInterval(20)
        self.setUpTimer.setSingleShot(True)
        self.setUpTimer.timeout.connect(self.setAreas)
        self.setUpTimer.start()

    def connections(self):
        self.player.currentMediaChanged.connect(self.updateCurrentSong)
        self.player.durationChanged.connect(self.updateSongProgressRange)
        self.player.stateChanged.connect(self.playerStatusChanged)
        self.mediaControlArea.previousButton.click.connect(
            self.playlist.previous)
        self.mediaControlArea.repeatButton.click.connect(
            self.repeatButtonClick)
        self.mediaControlArea.stopButton.click.connect(self.stopButtonClick)
        self.mediaControlArea.playButton.click.connect(self.playButtonClick)
        self.mediaControlArea.randomButton.click.connect(
            self.randomButtonClick)
        self.mediaControlArea.nextButton.click.connect(self.playlist.next)
        self.mediaControlArea.muteButton.click.connect(self.mute)
        self.mediaControlArea.songProgress.sliderMoved.connect(
            self.songProgressMove)
        self.mediaControlArea.volumeControl.sliderMoved.connect(
            self.volumeChange)

    def setAreas(self) -> None:
        """Called after the GUI is created to provide user with a feedback
        that the program is running in case a larger amount of songs will be added
        when the Library class is initialized."""
        # TODO add a tooltip that will notify the user larger amount of songs is being loaded
        #  (freezes the program as the execution moves to the Library class.)
        self.library = library.Library()
        self.types = {
            "artist": self.library.getSongsForArtist,
            "album": self.library.getSongsForAlbum,
            "playlist": self.library.getSongsForPlaylist
        }
        self.mainArea.setAreas(self.library)
        self.setUpTimer.deleteLater()
        self.setUpTimer = None
        self.getSongs(self.displayedType, self.displayedName)
        if self.songListWidth is not None:
            songListGeometry = self.songList.geometry()
            self.songList.preferredWidth = songListGeometry.width(
            ) - self.songListWidth
            self.mainWindow.centralWidget().upperBox.line.resizeWidgets(
                songListGeometry.width() - self.songListWidth)

    def updateLibrary(self) -> None:
        self.library.update()
        self.mainArea.updateView(self.library)

    def updateCurrentSong(self) -> None:
        """Update all areas that may display information about the currently
        playing song - SongList, Now Playing tab, BottomBox"""
        media = self.player.currentMedia()
        self.currentSong = media.request().url().toLocalFile().replace(
            "/", "\\")
        if self.currentSong in self.library.library:
            self.songList.updateActiveSong(self.currentSong)
            self.mainArea.updateActiveSong(self.playlist.currentIndex())
            songEntry = self.library.library[self.currentSong]
            self.mediaControlArea.updateSongInfo(
                f"{songEntry[ARTIST]} - {songEntry[NAME]}")

    def updateSongProgressRange(self) -> None:
        """Updates the range of the slider that represents the song position."""
        self.mediaControlArea.updateSongProgressRange(self.player.duration())

    def playerStatusChanged(self) -> None:
        """Used to properly update the player look after the current playlist has finished."""
        index = self.playlist.currentIndex()
        if index == -1:
            self.stopButtonClick()

    def getSongs(self, isType: str, name: str) -> None:
        """Retrieves the songs for a given artist, album or playlist based on type
        and passes the resulting list to the SongList class."""
        if isType is None:
            isType = self.displayedType
        if name is None:
            name = self.displayedName
        orderBy = self.songList.buttonOrderBy.text()
        reverse = True if self.songList.buttonOrderReverse.text() == chr(
            0x25bc) else False
        listForType = self.types[isType](name, orderBy, reverse)
        playlist = None
        if isType == "playlist":
            playlist = name
        if len(listForType) == 0:
            artists = self.library.artists
            if len(artists):
                listForType = self.library.getSongsForArtist(artists[0])
        self.songList.updateSongList(listForType, self.library.library,
                                     self.currentSong, playlist, isType)
        self.displayedType = isType
        self.displayedName = name

    def playSongList(self, song: str = None) -> None:
        """Called when user double-clicks on an artist/album/playlist widget or a song
        in right-hand side panel."""
        self.playlist.clear()
        index = 0
        loopIndex = 0
        for songPath in self.songList.garbageProtector:
            if song == songPath:
                index = loopIndex
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(songPath)))
            loopIndex += 1
        if self.playlist.isEmpty():
            return
        self.player.play()
        if index > 0:
            self.playlist.setCurrentIndex(index)
        self.playing = True
        self.mediaControlArea.playButton.updatePictures(
            bottom.pausePixmap, bottom.pauseHoverPixmap, False)
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playSongWidget(self,
                       songPath: str,
                       afterCurrent: bool = False) -> None:
        if afterCurrent:
            index = self.playlist.currentIndex() + 1
            self.playlist.insertMedia(
                index, QMediaContent(QUrl.fromLocalFile(songPath)))
        else:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(songPath)))
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())
        self.playing = True

    def removeFromNowPlaying(self, widget) -> None:
        if self.playlist.mediaCount() > 1:
            for row in range(self.mainArea.nowPlayingLayout.rowCount()):
                for column in range(
                        self.mainArea.nowPlayingLayout.columnCount()):
                    if self.mainArea.nowPlayingLayout.itemAtPosition(
                            row, column).widget() is widget:
                        self.playlist.removeMedia(row - 1)
                        break
                else:
                    continue
                break
        else:
            self.stopButtonClick()
            self.playlist.clear()
        self.mainArea.setNowPlayingArea(self.library)
        if self.playing:
            self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playMediaWidget(self, isType: str, target: str, startOver: bool,
                        afterCurrent: bool) -> None:
        """Called from MediaWidget - plays all songs for MediaWidget's type and name."""
        if startOver:
            self.playlist.clear()
        if afterCurrent:
            index = self.playlist.currentIndex() + 1
            for songPath in self.types[isType](target):
                self.playlist.insertMedia(
                    index, QMediaContent(QUrl.fromLocalFile(songPath)))
                index += 1
        else:
            for songPath in self.types[isType](target):
                self.playlist.addMedia(
                    QMediaContent(QUrl.fromLocalFile(songPath)))
        if startOver:
            self.player.play()
            self.playing = True
            self.mediaControlArea.playButton.updatePictures(
                bottom.pausePixmap, bottom.pauseHoverPixmap, False)
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playFromNowPlaying(self, song: str) -> None:
        """Called when user double-clicks on a song in the Now Playing tab."""
        for n in range(self.playlist.mediaCount()):
            media = self.playlist.media(n)
            if song == media.request().url().toLocalFile().replace("/", "\\"):
                self.playlist.setCurrentIndex(n)
                if not self.playing:
                    self.player.play()
                    self.playing = True
                return

    def createPlaylist(self, playlistName: str) -> None:
        self.library.createPlaylist(playlistName)
        self.mainArea.setMainAreaPlaylists(self.library)

    def addToExistingPlaylist(self, playlist: str, songOrWidget: str,
                              isType: str) -> None:
        if isType in self.types:
            for song in self.types[isType](songOrWidget):
                self.library.addToPlaylist(playlist, song)
        else:
            self.library.addToPlaylist(playlist, songOrWidget)
        self.library.update()

    def removeFromPlaylist(self, playlist: str, song: str) -> None:
        self.library.deleteFromPlaylist(playlist, song)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()
        self.getSongs("playlist", playlist)

    def renamePlaylist(self, playlistName: str, newPlaylistName: str) -> None:
        self.library.renamePlaylist(playlistName, newPlaylistName)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()

    def deletePlaylist(self, playlistName: str) -> None:
        self.library.deletePlaylist(playlistName)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()

    def addWatchedFolder(self, folder: str) -> None:
        """Adds a folder to the Library class. all mp3 files within the folder
        and its sub-folders will be added to the library and accessible to the player."""
        self.library.addFolder(folder.replace("/", "\\"))
        self.mainArea.updateView(self.library)

    def removeWatchedFolder(self, folder: str) -> None:
        """Removes folder from the library, updates view and stops playback if
        the current song was in the now-removed folder."""
        self.library.deleteFolder(folder)
        self.mainArea.updateView(self.library)
        if self.currentSong not in self.library.library:
            self.songList.updateSongList([], [], "", "")
            self.player.stop()
            self.playlist.clear()
            self.mediaControlArea.updateSongInfo("")
            self.songList.nowPlayingSong = None
            self.mainArea.nowPlayingSong = None
            self.playing = False
            self.mediaControlArea.updatePlayButton(self.playing, False)

    def playButtonClick(self, passMove: bool = True) -> None:
        if not self.playing:
            if self.playlist.isEmpty():
                self.playSongList()
                return
            self.playing = True
            self.player.play()
            self.mainArea.updateActiveSong(self.playlist.currentIndex())
            self.songList.updateActiveSong(self.currentSong)
        else:
            self.playing = False
            self.player.pause()
        self.mediaControlArea.updatePlayButton(self.playing, passMove)

    def repeatButtonClick(self) -> None:
        if self.repeat == 0:
            self.repeat = 1
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        elif self.repeat == 1:
            self.repeat = 2
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        elif self.repeat == 2:
            self.repeat = 0
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.mediaControlArea.updateRepeatButton(self.repeat)

    def randomButtonClick(self) -> None:
        if not self.random:
            self.random = True
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
        else:
            self.random = False
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.mediaControlArea.updateRandomButton(self.random)

    def stopButtonClick(self) -> None:
        self.playing = False
        self.player.stop()
        if self.songList.nowPlayingSong is not None:
            self.songList.nowPlayingSong.clear()
        if self.mainArea.nowPlayingSong is not None:
            self.mainArea.nowPlayingSong.clear()
        self.mediaControlArea.updatePlayButton(self.playing, False)

    def mute(self) -> None:
        if not self.player.isMuted():
            self.player.setMuted(True)
            self.mediaControlArea.showMute()
        else:
            self.player.setMuted(False)
            self.volumeChange(self.volume)

    def volumeChange(self, volume: int) -> None:
        logVolume = QAudio.convertVolume(volume / 100,
                                         QAudio.LogarithmicVolumeScale,
                                         QAudio.LinearVolumeScale) * 100
        self.player.setVolume(logVolume)
        self.volume = volume
        self.mediaControlArea.updateVolumeBar(volume)

    def songProgressMove(self, position: int) -> None:
        self.player.setPosition(position)

    def updateSongProgress(self) -> None:
        position = self.player.position()
        if 0 <= position < 2_000_000_000:
            if self.player.state() > 0:
                self.mediaControlArea.updateSongProgress(position)
                if self.playing:
                    self.songList.activeSongPixmap()
                    self.mainArea.activeSongPixmap()
            else:
                self.mediaControlArea.updateSongProgress(0)

    def disconnect(self):
        self.player.currentMediaChanged.disconnect()
        self.player.durationChanged.disconnect()
        self.player.stateChanged.disconnect()
        self.mediaControlArea.previousButton.click.disconnect()
        self.mediaControlArea.repeatButton.click.disconnect()
        self.mediaControlArea.stopButton.click.disconnect()
        self.mediaControlArea.playButton.click.disconnect()
        self.mediaControlArea.randomButton.click.disconnect()
        self.mediaControlArea.nextButton.click.disconnect()
        self.mediaControlArea.muteButton.click.disconnect()
        self.mediaControlArea.songProgress.sliderMoved.disconnect()
        self.mediaControlArea.volumeControl.sliderMoved.disconnect()

    def close(self) -> None:
        self.disconnect()
        self.player.stop()
        self.mainTimer.stop()
        self.save()

    def save(self) -> None:
        """Called on exit, saves current view, geometry and volume."""
        with gzip.open(r"musicplayer\mpdata", "wb") as fh:
            fh.write(self.MAGIC)
            toBeWritten = struct.pack(f"<h{len(self.displayedType.encode())}s",
                                      len(self.displayedType.encode()),
                                      self.displayedType.encode())
            fh.write(toBeWritten)
            fh.write(self.MAGIC)
            toBeWritten = struct.pack(f"<h{len(self.displayedName.encode())}s",
                                      len(self.displayedName.encode()),
                                      self.displayedName.encode())
            fh.write(toBeWritten)
            fh.write(self.MAGIC)
            geo = self.mainWindow.geometry()
            toBeWritten = struct.pack("<4h", geo.x(), geo.y(), geo.width(),
                                      geo.height())
            fh.write(toBeWritten)
            toBeWritten = struct.pack("<h", self.volume)
            fh.write(toBeWritten)
            toBeWritten = struct.pack("<h", self.songList.width())
            fh.write(toBeWritten)

    def load(self) -> [bool, tuple]:
        """Called on startup, loads view, geometry and volume saved on previous run."""
        try:
            with gzip.open(r"musicplayer\mpdata", "rb") as fh:
                if not fh.read(2) == self.MAGIC:
                    return False
                length = fh.read(2)
                length = struct.unpack("<h", length)[0]
                displayedType = fh.read(length)
                displayedType = struct.unpack(f"<{length}s",
                                              displayedType)[0].decode("utf8")
                if displayedType in ["artist", "album", "playlist"]:
                    self.displayedType = displayedType
                if not fh.read(2) == self.MAGIC:
                    return False
                length = fh.read(2)
                length = struct.unpack("<h", length)[0]
                displayedName = fh.read(length)
                displayedName = struct.unpack(f"<{length}s",
                                              displayedName)[0].decode("utf8")
                if not fh.read(2) == self.MAGIC:
                    return False
                self.displayedName = displayedName
                variables = []
                for n in range(6):
                    var = fh.read(2)
                    var = struct.unpack("<h", var)[0]
                    variables.append(var)
                x, y, width, height, volume, songListWidth = variables
                self.volume = volume
                self.songListWidth = songListWidth
                return x, y, width, height
        except Exception:
            return False
Ejemplo n.º 37
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())
Ejemplo n.º 38
0
class Music_Player(QWidget, Ui_Form):

    with open("path.txt", 'r') as f:
        home_dir = f.read()
        home_dir = home_dir.rstrip()

    def __init__(self):
        #super(Music_Player, self).__init__()
        super().__init__()
        #set up the user interface from Designer
        self.setupUi(self)

        # this gets the inforation needed for the table
        lib = []
        directory = os.path.join(Music_Player.home_dir, "Music")

        walk = os.walk(directory)
        for root, dirs, files in walk:
            for file in files:
                path = os.path.join(root, file)
                if file.endswith(
                        '.mp3'):  # then we should add file to library\
                    song = os.path.splitext(file)[0]
                    song = song.replace('_', ' ')

                    # using eyed3 to get song info
                    audiofile = eyed3.load(path)
                    artist = audiofile.tag.artist
                    album = audiofile.tag.album
                    length_secs = audiofile.info.time_secs  # seconds
                    length_formatted = seconds_to_minutes(length_secs)

                    # list of lists with information
                    lib.append([
                        song, artist, album, length_formatted, path,
                        str(length_secs)
                    ])  # length shows seconds

        # usedfor the functions
        self.library = lib

        self.songTableWidget_tab3.setRowCount(len(lib))
        self.songTableWidget_2.setRowCount(len(lib))
        self.songTableWidget.setRowCount(len(lib))
        self.songTableWidget.setColumnHidden(4, True)  #hide path column
        self.songTableWidget.setColumnHidden(
            5, True)  #hide length column that shows seconds
        self.songTableWidget_2.setColumnHidden(4, True)  #hide path column
        self.songTableWidget_2.setColumnHidden(
            5, True)  #hide length column that shows seconds
        self.songTableWidget_tab3.setColumnHidden(4, True)  #hide path column
        self.songTableWidget_tab3.setColumnHidden(
            5, True)  #hide length column that shows seconds
        self.songTableWidget.setEditTriggers(
            QAbstractItemView.NoEditTriggers)  # no way to edit items
        self.songTableWidget_tab3.setEditTriggers(
            QAbstractItemView.NoEditTriggers)

        # setting the column widths
        self.songTableWidget.setColumnWidth(0, 220)
        self.songTableWidget.setColumnWidth(1, 160)
        self.songTableWidget.setColumnWidth(2, 165)
        self.songTableWidget.setColumnWidth(3, 60)

        # setting up touch scrolling for the songTableWidget
        scroller = QScroller.scroller(self.songTableWidget)
        QScroller.grabGesture(self.songTableWidget,
                              QScroller.LeftMouseButtonGesture)

        # setting up touch scrolling for the playlistTableWidget_2
        scroller_playlist_2 = QScroller.scroller(self.playlistTableWidget_2)
        QScroller.grabGesture(self.playlistTableWidget_2,
                              QScroller.LeftMouseButtonGesture)

        # setting up touch scrolling for the songTableWidget_2
        scroller_2 = QScroller.scroller(self.songTableWidget_2)
        QScroller.grabGesture(self.songTableWidget_2,
                              QScroller.LeftMouseButtonGesture)

        # setting up touch scrolling for the songTableWidget_tab3
        scroller_3 = QScroller.scroller(self.songTableWidget_tab3)
        QScroller.grabGesture(self.songTableWidget_tab3,
                              QScroller.LeftMouseButtonGesture)

        # populating the table
        for i in range(len(lib)):  #number of rows
            for k in range(6):  # there are 6 columns
                item = QTableWidgetItem(lib[i][k])
                item2 = QTableWidgetItem(lib[i][k])
                item3 = QTableWidgetItem(lib[i][k])
                self.songTableWidget.setItem(i, k, item)
                self.songTableWidget_tab3.setItem(i, k, item2)  # for tab3
                self.songTableWidget_2.setItem(i, k, item3)

        self.songTableWidget.sortItems(0, Qt.AscendingOrder)
        self.songTableWidget_tab3.sortItems(0, Qt.AscendingOrder)  # tab 3

        # add the check mark boxes so they don't only appear when the song is played for the first time
        for i in range(self.songTableWidget.rowCount()):
            self.songTableWidget.item(i, 0).setCheckState(Qt.Unchecked)
            self.songTableWidget_2.item(i, 0).setCheckState(Qt.Unchecked)

        # setting up media Player
        self.player = QMediaPlayer(None)

        if not os.path.exists("log.txt"):
            with open("log.txt", 'w') as f:
                pass
        # the time doesn't work but the row does
        # this will load the last song played into the media player, though time will start from 0
        with open("log.txt", 'r') as f:
            info = f.read()

        if info:
            row = int(info.split(',')[0])
            self.time = int(
                info.split(',')[1]
            )  # used in mediaStatusChanged to allow for the startup time
            song_path = self.songTableWidget.item(row, 4).text()
            self.player.setMedia(QMediaContent(QUrl.fromLocalFile(song_path)))
            #self.player.play()

            # used by mediaStatusChanged to load in the correct place the player left off from
            #self.startup = 1

        else:
            row = 0
            default_song_path = self.songTableWidget.item(0, 4).text()
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(default_song_path)))

        # make adjustments
        self.volumeSlider.setMaximum(100)
        self.volumeSlider.setSliderPosition(100)
        self.volumeLabel.setText(str(100))

        self.songSlider.setMinimum(0)
        self.songSlider.setMaximum(
            int(self.songTableWidget.item(row, 5).text()))

        self.endLabel.setText(self.songTableWidget.item(row, 3).text())
        self.songPlayingLabel.setText(self.songTableWidget.item(row, 0).text())

        # tab 3 signals and slots
        self.saveButton_tab3.clicked.connect(self.save_click)
        self.searchEdit_tab3.textChanged.connect(self.search_edit)

        #conncect buttons
        self.volumeSlider.valueChanged.connect(self.volume_change)
        self.playButton.clicked.connect(self.play_click)
        self.songTableWidget.cellDoubleClicked.connect(self.double_click)
        self.player.stateChanged.connect(
            self.state_changed)  # playing, paused, no media
        self.player.positionChanged.connect(self.position_changed)
        self.player.mediaStatusChanged.connect(
            self.media_status)  # #loading media, end of media, etc.
        self.player.currentMediaChanged.connect(
            self.song_changed)  # when the song changes
        self.songSlider.sliderMoved.connect(self.slider_moved)
        self.songSlider.sliderReleased.connect(self.slider_released)
        self.nextButton.clicked.connect(self.next)
        self.prevButton.clicked.connect(self.prev)

        ##################################################################
        ###########################################################
        #################### tab 2 #############################\

        self.finaldeleteButton_2.setVisible(False)

        self.player_2 = QMediaPlayer(None)
        self.player_2.setVolume(100)

        # make adjustments
        self.volumeSlider_2.setMaximum(100)
        self.volumeSlider_2.setSliderPosition(100)
        self.volumeLabel_2.setText(str(100))

        self.endLabel_2.setText(self.songTableWidget_2.item(0, 3).text())
        self.songPlayingLabel_2.setText(
            self.songTableWidget_2.item(0, 0).text())

        self.playlistTableWidget_2.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.songTableWidget_2.setEditTriggers(
            QAbstractItemView.NoEditTriggers)

        #conncect buttons
        self.volumeSlider_2.valueChanged.connect(self.volume_change_2)
        self.playButton_2.clicked.connect(self.play_click_2)
        self.songTableWidget_2.cellDoubleClicked.connect(self.double_click_2)
        self.player_2.stateChanged.connect(
            self.state_changed_2)  # playing, paused, no media
        self.player_2.positionChanged.connect(self.position_changed_2)
        self.player_2.mediaStatusChanged.connect(
            self.media_status_2)  # #loading media, end of media, etc.
        self.player_2.currentMediaChanged.connect(
            self.song_changed_2)  # when the song changes
        self.songSlider_2.sliderMoved.connect(self.slider_moved_2)
        self.songSlider_2.sliderReleased.connect(self.slider_released_2)
        self.nextButton_2.clicked.connect(self.next_2)
        self.prevButton_2.clicked.connect(self.prev_2)

        # if there are playlists present on the system we want to list them
        files = os.listdir(Music_Player.home_dir +
                           "/Desktop/music_player/playlists")
        if files:
            self.playlistTableWidget_2.setRowCount(len(files))
            playlist_names = [os.path.splitext(file)[0] for file in files]

            x = 0
            for file in files:
                with open(
                        Music_Player.home_dir +
                        '/Desktop/music_player/playlists/{}'.format(file),
                        'r') as f:
                    lines = f.readlines()
                    amount_of_songs = lines[-2]
                    date_added = lines[-1]
                playlist_name = os.path.splitext(file)[0]
                item_1 = QTableWidgetItem(playlist_name)
                item_2 = QTableWidgetItem(amount_of_songs)
                item_3 = QTableWidgetItem(date_added)
                self.playlistTableWidget_2.setItem(x, 0, item_1)
                self.playlistTableWidget_2.setItem(x, 1, item_2)
                self.playlistTableWidget_2.setItem(x, 2, item_3)
                x = x + 1

        self.playlistTableWidget_2.cellDoubleClicked.connect(
            self.choose_playlist)
        self.playlist_button_2.clicked.connect(self.back_to_playlists)
        self.deleteButton_2.clicked.connect(self.delete_button_2)
        self.finaldeleteButton_2.clicked.connect(self.finaldelete_clicked_2)

    def delete_button_2(self):
        if self.deleteButton_2.isChecked():
            self.playlistTableWidget_2.setSelectionMode(
                QtWidgets.QAbstractItemView.MultiSelection)
            # show delete button
            self.finaldeleteButton_2.setVisible(True)
        if self.deleteButton_2.isChecked() == False:
            self.playlistTableWidget_2.setSelectionMode(
                QtWidgets.QAbstractItemView.ExtendedSelection)
            self.finaldeleteButton_2.setVisible(False)

    def finaldelete_clicked_2(self):
        items = self.playlistTableWidget_2.selectedItems(
        )  # will have many duplicates in the list that is returned
        if items:  # if list is not empty
            pass
        else:
            self.finalDeleteLabel_2.setText("Must Select Playlist[s]")

    def back_to_playlists(self):
        self.stackedWidget.setCurrentIndex(0)

    def choose_playlist(self, row, column):  # when the playlist is clicked
        ## get back to neutral so we don't keep removing songs from table

        self.songTableWidget_2.sortItems(0, Qt.AscendingOrder)
        count = self.songTableWidget_2.rowCount()
        for k in range(count):
            self.songTableWidget_2.setRowHidden(k, False)

        playlist_name = self.playlistTableWidget_2.item(row, 0).text()
        self.stackedWidget.setCurrentIndex(1)
        self.playlist_name_2.setText(playlist_name)
        with open(
                Music_Player.home_dir +
                '/Desktop/music_player/playlists/{}.txt'.format(playlist_name),
                'r') as f:
            songs = f.readlines(
            )[:
              -2]  # the last two lines are amount of songs in the playlist and the date the playlist was created
            songs = [song.rstrip() for song in songs]

        items = []
        for song in songs:
            items.append(
                self.songTableWidget_2.findItems(song, Qt.MatchContains))
        items = [item[0] for item in items]
        rows = {i.row() for i in items}

        # hiding the songs not in playlist
        for k in range(count):
            if k not in rows:
                self.songTableWidget_2.setRowHidden(k, True)

    def prev_2(self):
        path = self.player_2.currentMedia().canonicalUrl().path()
        item = self.songTableWidget_2.findItems(path, Qt.MatchExactly)
        row = item[0].row()  # gives the index starting at 0
        #print(row, self.songTableWidget.rowCount())

        if self.player_2.position() >= 2000:
            self.player_2.setPosition(0)
            return True

        if row == 0:
            print("row==0")
            for i in range(1, self.songTableWidget_2.rowCount()):
                next_row = self.songTableWidget_2.rowCount(
                ) - i  # row count starts counting at 1 so index = rowCount -1
                if self.songTableWidget_2.isRowHidden(next_row):
                    continue
                else:
                    break
            new_song_path = self.songTableWidget_2.item(next_row, 4).text()
        else:
            for i in range(
                    1,
                    self.songTableWidget_2.rowCount()):  # 1 to the row count
                next_row = row - i  # all you need is 1 minus the row count to make the list full circle
                if next_row < 0:
                    next_row = self.songTableWidget_2.rowCount(
                    ) + next_row  # then we need be back at the last index

                if self.songTableWidget_2.isRowHidden(next_row):
                    continue
                else:
                    break
            new_song_path = self.songTableWidget_2.item(next_row, 4).text()

        if self.player_2.state() == QMediaPlayer.PlayingState:
            self.player_2.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))
            self.player_2.play()
        else:
            self.player_2.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))

    def next_2(self):
        path = self.player_2.currentMedia().canonicalUrl().path()
        item = self.songTableWidget_2.findItems(path, Qt.MatchExactly)
        row = item[0].row()  # gives the index starting at 0

        if self.songTableWidget_2.rowCount() == (
                row + 1):  # then we are at end of table
            next_row = 0
            if self.songTableWidget_2.isRowHidden(next_row):
                for i in range(1, self.songTableWidget_2.rowCount()):
                    next_row = next_row + i
                    if self.songTableWidget_2.isRowHidden(next_row):
                        continue
                    else:
                        break

            new_song_path = self.songTableWidget_2.item(next_row, 4).text()

        else:
            for i in range(1, self.songTableWidget_2.rowCount()):
                next_row = row + i
                if next_row >= self.songTableWidget_2.rowCount(
                ):  # then the index is out of range
                    next_row = next_row - self.songTableWidget_2.rowCount()
                if self.songTableWidget_2.isRowHidden(next_row):
                    continue
                else:
                    break
            new_song_path = self.songTableWidget_2.item(next_row, 4).text()

        if self.player_2.state() == QMediaPlayer.PlayingState:
            self.player_2.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))
            self.player_2.play()
        else:
            self.player_2.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))

    def slider_moved_2(self, value):  # signal when slider is pressed down
        if self.songSlider_2.isSliderDown():
            time = seconds_to_minutes(value)
            self.startLabel_2.setText(time)

    def slider_released_2(self):
        seconds = self.songSlider_2.sliderPosition()
        self.player_2.setPosition(seconds * 1000)

    def song_changed_2(self, song):  # takes QMediaContent
        path = (song.canonicalUrl().path()
                )  # path of song used to locate row in table
        item = self.songTableWidget_2.findItems(path, Qt.MatchExactly)
        row = item[0].row()  # there can only be one match in the list

        self.songPlayingLabel_2.setText(
            self.songTableWidget_2.item(row, 0).text())
        self.endLabel_2.setText(self.songTableWidget_2.item(row, 3).text())
        self.songSlider_2.setMaximum(
            int(self.songTableWidget_2.item(row, 5).text()))

        # now need to setup how the slider will work
        # when slider is pressed down song still plays at normal pace but start label adjusts to where the slider is
        # shen slider is released then move the song to that position

    def media_status_2(self, status):  # takes QMediaPlayer.MediaStatus
        if status == QMediaPlayer.BufferedMedia:
            # get rid of all the check marks on the songs that have been played
            for i in range(self.songTableWidget_2.rowCount()):
                self.songTableWidget_2.item(i, 0).setCheckState(Qt.Unchecked)
            path = self.player_2.currentMedia().canonicalUrl().path()
            item = self.songTableWidget_2.findItems(
                path, Qt.MatchExactly)  #qtbalewidgetitem
            row = item[0].row(
            )  # this finds the row that the qtablewidgetitem originates
            self.songTableWidget_2.item(row, 0).setCheckState(Qt.Checked)
        elif status == QMediaPlayer.EndOfMedia:
            path = self.player_2.currentMedia().canonicalUrl().path()
            item = self.songTableWidget_2.findItems(
                path, Qt.MatchExactly)  #qtbalewidgetitem
            row = item[0].row(
            )  # this finds the row that the qtablewidgetitem originates
            self.songTableWidget_2.item(row, 0).setCheckState(Qt.Unchecked)
            print("end of media")

    def position_changed_2(self,
                           position):  # position is expressed in milleseconds
        seconds = int(position / 1000)  # now its in seconds
        if self.songSlider_2.isSliderDown() == False:
            self.songSlider_2.setSliderPosition(seconds)
            time = seconds_to_minutes(seconds)
            self.startLabel_2.setText(time)

    def state_changed_2(self, state):
        if self.player_2.state() == QMediaPlayer.PlayingState:
            self.playButton_2.setText("Pause")
            # turns the library player off
            self.player.pause()
        if self.player_2.state(
        ) == QMediaPlayer.PausedState or self.player_2.state(
        ) == QMediaPlayer.StoppedState:
            self.playButton_2.setText("Play")

    def play_click_2(self):
        if self.player_2.state() == 1:  # playing state
            self.player_2.pause()
        elif self.player_2.state() == 2:  # paused state
            self.player_2.play()
        else:  # stopped state which = 0
            self.player_2.play()

    def volume_change_2(self, value):
        self.volumeLabel_2.setText(str(value))
        self.player_2.setVolume(value)

    def double_click_2(self, row, column):  #row and column are ints
        song = self.songTableWidget_2.item(
            row, 0).text()  # this is the cell with song name
        # returns the qtablewidgetitem need to change it to text
        path = self.songTableWidget_2.item(row, 4).text()
        self.songPlayingLabel_2.setText(song)
        self.player_2.setMedia(QMediaContent(QUrl.fromLocalFile(path)))
        self.player_2.play()


#####################################################################################
#####################################################################################
#################################### tab 3 ###########################################
#####################################################################################
#####################################################################################

    def search_edit(self, text):
        # reset at the beginnning so that everything shows up
        count = self.songTableWidget_tab3.rowCount()
        for k in range(count):
            self.songTableWidget_tab3.setRowHidden(k, False)

        items = self.songTableWidget_tab3.findItems(text, Qt.MatchContains)
        rows = {i.row() for i in items}

        count = self.songTableWidget_tab3.rowCount()
        for k in range(count):
            if k not in rows:
                self.songTableWidget_tab3.setRowHidden(k, True)

    def save_click(self):
        playlist_name = self.playlistNameEdit_tab3.text()
        if playlist_name:  # will need to check that there is no other playlist name that has the same Name
            if self.songTableWidget_tab3.selectedItems():
                rows_selected = {
                    i.row()
                    for i in self.songTableWidget_tab3.selectedItems()
                }
                songs_selected = [
                    self.songTableWidget_tab3.item(i, 4).text()
                    for i in rows_selected
                ]
                print(rows_selected)
                print(songs_selected)

                with open(
                        Music_Player.home_dir +
                        '/Desktop/music_player/playlists/{}.txt'.format(
                            playlist_name), 'w') as f:
                    for i in songs_selected:
                        f.write(i + '\n')
                    f.write(str(len(songs_selected)) + '\n')
                    f.write(str(datetime.datetime.now()))

                # update the playlist table in tab2
                files = os.listdir(Music_Player.home_dir +
                                   '/Desktop/music_player/playlists')
                if files:
                    self.playlistTableWidget_2.setRowCount(len(files))
                    playlist_names = [
                        os.path.splitext(file)[0] for file in files
                    ]

                    x = 0
                    for file in files:
                        with open(
                                Music_Player.home_dir +
                                '/Desktop/music_player/playlists/{}'.format(
                                    file), 'r') as f:
                            lines = f.readlines()
                            amount_of_songs = lines[-2]
                            date_added = lines[-1]
                        playlist_name = os.path.splitext(file)[0]
                        item_1 = QTableWidgetItem(playlist_name)
                        item_2 = QTableWidgetItem(amount_of_songs)
                        item_3 = QTableWidgetItem(date_added)
                        self.playlistTableWidget_2.setItem(x, 0, item_1)
                        self.playlistTableWidget_2.setItem(x, 1, item_2)
                        self.playlistTableWidget_2.setItem(x, 2, item_3)
                        x = x + 1

            else:
                self.playlist_verifier_tab3.setText("Need to Select Songs")

        else:
            self.playlist_verifier_tab3.setText("Not a Valid Name")

    ##############################################################
    ###########################################################
    #################### tab 1 #############################

    def prev(self):
        path = self.player.currentMedia().canonicalUrl().path()
        item = self.songTableWidget.findItems(path, Qt.MatchExactly)
        row = item[0].row()  # gives the index starting at 0
        #print(row, self.songTableWidget.rowCount())

        if self.player.position() >= 2000:
            self.player.setPosition(0)
            return True

        if row == 0:
            next_row = self.songTableWidget.rowCount(
            ) - 1  # row count starts counting at 1 so index = rowCount -1
            new_song_path = self.songTableWidget.item(next_row, 4).text()
        else:
            next_row = row - 1
            new_song_path = self.songTableWidget.item(next_row, 4).text()

        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))
            self.player.play()
        else:
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))

    def next(self):
        path = self.player.currentMedia().canonicalUrl().path()
        item = self.songTableWidget.findItems(path, Qt.MatchExactly)
        row = item[0].row()  # gives the index starting at 0

        if self.songTableWidget.rowCount() == (
                row + 1):  # then we are at end of table
            next_row = 0
            new_song_path = self.songTableWidget.item(next_row, 4).text()

        else:
            next_row = row + 1
            new_song_path = self.songTableWidget.item(next_row, 4).text()

        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))
            self.player.play()
        else:
            self.player.setMedia(
                QMediaContent(QUrl.fromLocalFile(new_song_path)))

    def slider_moved(self, value):  # signal when slider is pressed down
        if self.songSlider.isSliderDown():
            time = seconds_to_minutes(value)
            self.startLabel.setText(time)

    def slider_released(self):
        seconds = self.songSlider.sliderPosition()
        self.player.setPosition(seconds * 1000)

    def song_changed(self, song):  # takes QMediaContent
        path = (song.canonicalUrl().path()
                )  # path of song used to locate row in table
        item = self.songTableWidget.findItems(path, Qt.MatchExactly)
        row = item[0].row()  # there can only be one match in the list

        self.songPlayingLabel.setText(self.songTableWidget.item(row, 0).text())
        self.endLabel.setText(self.songTableWidget.item(row, 3).text())
        self.songSlider.setMaximum(
            int(self.songTableWidget.item(row, 5).text()))

        # now need to setup how the slider will work
        # when slider is pressed down song still plays at normal pace but start label adjusts to where the slider is
        # shen slider is released then move the song to that position

    def media_status(self, status):  # takes QMediaPlayer.MediaStatus
        if status == QMediaPlayer.BufferedMedia:
            # get rid of all the check marks on the songs that have been played
            for i in range(self.songTableWidget.rowCount()):
                self.songTableWidget.item(i, 0).setCheckState(Qt.Unchecked)
            path = self.player.currentMedia().canonicalUrl().path()
            item = self.songTableWidget.findItems(
                path, Qt.MatchExactly)  #qtbalewidgetitem
            row = item[0].row(
            )  # this finds the row that the qtablewidgetitem originates
            self.songTableWidget.item(row, 0).setCheckState(Qt.Checked)
        elif status == QMediaPlayer.EndOfMedia:
            path = self.player.currentMedia().canonicalUrl().path()
            item = self.songTableWidget.findItems(
                path, Qt.MatchExactly)  #qtbalewidgetitem
            row = item[0].row(
            )  # this finds the row that the qtablewidgetitem originates
            self.songTableWidget.item(row, 0).setCheckState(Qt.Unchecked)
            print("end of media")

    def position_changed(self,
                         position):  # position is expressed in milleseconds
        seconds = int(position / 1000)  # now its in seconds
        if self.songSlider.isSliderDown() == False:
            self.songSlider.setSliderPosition(seconds)
            time = seconds_to_minutes(seconds)
            self.startLabel.setText(time)

    def state_changed(self, state):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.playButton.setText("Pause")
            self.player_2.pause()

        if self.player.state(
        ) == QMediaPlayer.PausedState or self.player.state(
        ) == QMediaPlayer.StoppedState:
            self.playButton.setText("Play")

    def play_click(self):
        if self.player.state() == 1:  # playing state
            self.player.pause()
        elif self.player.state() == 2:  # paused state
            self.player.play()
        else:  # stopped state which = 0
            self.player.play()

    def volume_change(self, value):
        self.volumeLabel.setText(str(value))
        self.player.setVolume(value)

    def double_click(self, row, column):  #row and column are ints
        song = self.songTableWidget.item(
            row, 0).text()  # this is the cell with song name
        # returns the qtablewidgetitem need to change it to text
        path = self.songTableWidget.item(row, 4).text()
        self.songPlayingLabel.setText(song)
        self.player.setMedia(QMediaContent(QUrl.fromLocalFile(path)))
        self.player.play()
        #self.songTableWidget.

    def closeEvent(self, event):
        path = self.player.currentMedia().canonicalUrl().path()
        item = self.songTableWidget.findItems(
            path, Qt.MatchExactly)  #qtbalewidget item
        row = item[0].row(
        )  # this finds the row that the qtablewidgetitem originates
        time = int(
            self.player.position() /
            1000) - 1  # saves the milliseconds from the beginning of the song
        with open('log.txt', 'w') as f:
            info = "{},{}".format(str(row), str(time))
            f.write(info)
        event.accept()
Ejemplo n.º 39
0
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1200, 720)
        Form.setMinimumSize(QtCore.QSize(200, 199))
        Form.setStyleSheet("background-color:black;")

        self.isOnline = False
        self.isMini = False
        self.isOnTop = True
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        self.verticalLayout_2 = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_2.setSpacing(0)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        self.mainFrame = QtWidgets.QFrame(Form)
        self.mainFrame.setMinimumSize(QtCore.QSize(200, 82))
        self.mainFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.mainFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.mainFrame.setObjectName("mainFrame")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.mainFrame)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.frame_3 = QtWidgets.QFrame(self.mainFrame)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.frame_3.sizePolicy().hasHeightForWidth())
        self.frame_3.setSizePolicy(sizePolicy)
        self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_3.setObjectName("frame_3")
        self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.frame_3)
        self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_6.setObjectName("horizontalLayout_6")
        self.Player_name = QtWidgets.QLabel(self.frame_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.Player_name.sizePolicy().hasHeightForWidth())
        self.Player_name.setSizePolicy(sizePolicy)
        self.Player_name.setStyleSheet("QLabel\n"
                                       "    {\n"
                                       "    font: 12pt \"Helvetica\";\n"
                                       "    color: white;\n"
                                       "    border: 0px solid #076100;\n"
                                       "    }")
        self.Player_name.setObjectName("status_label")
        self.horizontalLayout_6.addWidget(self.Player_name)
        spacerItem = QtWidgets.QSpacerItem(40, 20,
                                           QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_6.addItem(spacerItem)
        self.minimize_button = QtWidgets.QPushButton(self.frame_3)
        self.minimize_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.minimize_button.setText("")
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("icon_sets/minimize.png"),
                       QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.minimize_button.setIconSize(QSize(25, 17))
        self.minimize_button.setMaximumSize(QSize(25, 17))
        self.minimize_button.setIcon(icon)
        self.minimize_button.setIconSize(QtCore.QSize(27, 20))
        # self.minimize_button.setFlat(True)
        self.minimize_button.setObjectName("minimize_button")
        self.horizontalLayout_6.addWidget(self.minimize_button)
        self.maximize_button = QtWidgets.QPushButton(self.frame_3)
        self.maximize_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.maximize_button.setText("")
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap("icon_sets/maximize.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.maximize_button.setIcon(icon1)
        self.maximize_button.setIconSize(QSize(25, 17))
        self.maximize_button.setMaximumSize(QSize(25, 17))
        self.maximize_button.setIconSize(QtCore.QSize(27, 20))
        # self.maximize_button.setFlat(True)
        self.maximize_button.setObjectName("maximize_button")
        self.horizontalLayout_6.addWidget(self.maximize_button)
        self.cross_button = QtWidgets.QPushButton(self.frame_3)
        self.cross_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.cross_button.setText("")
        self.cross_button.setIconSize(QSize(25, 17))
        self.cross_button.setMaximumSize(QSize(25, 17))
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap("icon_sets/cross.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.cross_button.setIcon(icon2)
        self.cross_button.setIconSize(QtCore.QSize(27, 20))
        # self.cross_button.setFlat(True)
        self.cross_button.setObjectName("cross_button")
        self.horizontalLayout_6.addWidget(self.cross_button)
        self.verticalLayout.addWidget(self.frame_3)

        self.video_playback = Videowidget(self.frame_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(200)
        sizePolicy.setHeightForWidth(
            self.video_playback.sizePolicy().hasHeightForWidth())
        self.video_playback.setSizePolicy(sizePolicy)
        self.video_playback.setMinimumSize(QtCore.QSize(200, 100))
        self.video_playback.setMouseTracking(False)
        self.video_playback.setTabletTracking(False)
        self.video_playback.setAcceptDrops(False)
        self.video_playback.setAutoFillBackground(False)
        self.video_playback.setObjectName("video_playback")
        self.video_playback.setStyleSheet("background-color:grey")

        self.verticalLayout.addWidget(self.video_playback)
        self.pos_frame = QtWidgets.QFrame(self.mainFrame)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(10)
        sizePolicy.setHeightForWidth(
            self.pos_frame.sizePolicy().hasHeightForWidth())
        self.pos_frame.setSizePolicy(sizePolicy)
        self.pos_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.pos_frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.pos_frame.setObjectName("pos_frame")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.pos_frame)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.position_slider = PosSlider(self.pos_frame)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(100)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.position_slider.sizePolicy().hasHeightForWidth())
        self.position_slider.setSizePolicy(sizePolicy)
        self.position_slider.setMouseTracking(True)
        self.position_slider.setAutoFillBackground(False)
        self.position_slider.setStyleSheet(
            "QSlider::handle:horizontal \n"
            "    {\n"
            "    background: transparent;\n"
            "    width: 8px;\n"
            "    }\n"
            "QSlider::groove:horizontal {\n"
            "    border: 1px solid white;\n"
            "    height: 8px;\n"
            "    background: qlineargradient(y1: 0, y2: 1,stop: 0 #2e3436, stop: 1.0 #000000);\n"
            "}\n"
            " QSlider::sub-page:horizontal {\n"
            "    background:qlineargradient( y1: 0, y2: 1,\n"
            "        stop: 0 #42a6db, stop: 1 #0074e0); \n"
            "    border: 1px solid white;\n"
            "    height: 8px;\n"
            "}\n"
            "QSlider::handle:horizontal:hover {\n"
            "    background: black;\n"
            "    height: 8px;\n"
            "    width: 8px;\n"
            "    border: 1px solid white;\n"
            "    }\n"
            "")
        self.position_slider.setOrientation(QtCore.Qt.Horizontal)
        self.position_slider.setInvertedAppearance(False)
        self.position_slider.setInvertedControls(False)
        self.position_slider.setObjectName("position_slider")
        self.horizontalLayout.addWidget(self.position_slider)

        self.time_status = QtWidgets.QLabel(self.pos_frame)
        font = QtGui.QFont()
        font.setFamily("Arial Rounded MT Bold")
        font.setPointSize(8)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.time_status.setFont(font)
        self.time_status.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    \n"
            "    font: 8pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "\n"
            "    }")
        self.time_status.setObjectName("time_status")
        self.horizontalLayout.addWidget(self.time_status)

        self.backslash = QtWidgets.QLabel(self.pos_frame)
        font = QtGui.QFont()
        font.setFamily("Arial Rounded MT Bold")
        font.setPointSize(8)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.backslash.setFont(font)
        self.backslash.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    \n"
            "    font: 8pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "\n"
            "    }")
        self.backslash.setObjectName("backslash")
        self.horizontalLayout.addWidget(self.backslash)

        self.duration_status = QtWidgets.QLabel(self.pos_frame)
        font = QtGui.QFont()
        font.setFamily("Arial Rounded MT Bold")
        font.setPointSize(8)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.duration_status.setFont(font)
        self.duration_status.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    \n"
            "    font: 8pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "\n"
            "    }")
        self.duration_status.setObjectName("duration_status")
        self.horizontalLayout.addWidget(self.duration_status)
        self.verticalLayout.addWidget(self.pos_frame)

        self.frame_2 = QtWidgets.QFrame(self.mainFrame)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(22)
        # sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())

        self.frame_2.setSizePolicy(sizePolicy)
        self.frame_2.setContentsMargins(0, 0, 0, 0)
        self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.frame_2.setStyleSheet("")
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.frame_2)
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")

        self.play_button = QtWidgets.QPushButton(self.frame_2)
        self.play_button.setEnabled(False)
        self.play_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.play_button.setStyleSheet(
            "QPushButton[play=true]{image:url(icon_sets/play/play.png);width:22px;height:22px}\n"
            "QPushButton[play=false]{image:url(icon_sets/pause/pause.png);width:22px;height:22px }\n"
        )
        self.play_button.setProperty("play", True)
        self.play_button.setText("")
        self.play_button.setObjectName("play_button")
        self.horizontalLayout_4.addWidget(self.play_button)

        self.playback_button = QtWidgets.QPushButton(self.frame_2)
        self.playback_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.playback_button.setStyleSheet(
            "QPushButton{image:url(icon_sets/playback/playback.png);width:22px;height:22px }\n"
        )
        self.playback_button.setText("")
        self.playback_button.setObjectName("playback_button")
        self.horizontalLayout_4.addWidget(self.playback_button)

        self.always_on_top_button = QtWidgets.QPushButton(self.frame_2)
        self.always_on_top_button.setCursor(
            QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.always_on_top_button.setStyleSheet(
            "QPushButton[top=false]{image : url(icon_sets/always_on_top/top_off.png) }\n"
            "QPushButton[top=true]{image : url(icon_sets/always_on_top/top_on.png) }\n"
        )
        self.always_on_top_button.setProperty("top", True)
        self.always_on_top_button.setText("")
        self.always_on_top_button.setObjectName("always_on_top_button")
        self.horizontalLayout_4.addWidget(self.always_on_top_button)

        self.miniplayer_button = QtWidgets.QPushButton(self.frame_2)
        self.miniplayer_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.miniplayer_button.setStyleSheet(
            "QPushButton[mini=false]{image : url(icon_sets/standard_player/standard.png) }\n"
            # "QPushButton[mini=false]:hover{ image:url(icon_sets/standard_player/.png) }\n"
            "QPushButton[mini=true]{image : url(icon_sets/mini_player/mini.png) }\n"
            # "QPushButton[mini=true]:hover{ image:url(icon_sets/mini_player/.png) }\n"
        )
        self.miniplayer_button.setProperty("mini", False)
        self.miniplayer_button.setContentsMargins(0, 0, 0, 0)
        self.miniplayer_button.setText("")
        self.miniplayer_button.setObjectName("miniplayer_button")
        self.horizontalLayout_4.addWidget(self.miniplayer_button)

        self.open_File_button = QtWidgets.QPushButton(self.frame_2)
        self.open_File_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.open_File_button.setStyleSheet(
            "QPushButton{image:url(icon_sets/new_file/new_file.png);width:22px;height:22px }\n"
        )
        self.open_File_button.setText("")
        self.open_File_button.setObjectName("playback_button")
        self.horizontalLayout_4.addWidget(self.open_File_button)

        spacerItem1 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem1)

        self.screenshot_button = QtWidgets.QPushButton(self.frame_2)
        self.screenshot_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.screenshot_button.setStyleSheet(
            "QPushButton{image : url(icon_sets/snapshot/snapshot.png);width:22px;height:22px} \n"
        )
        self.screenshot_button.setText("")
        self.screenshot_button.setObjectName("screenshot_button")
        self.horizontalLayout_4.addWidget(self.screenshot_button)
        ''' Video Setting button for Video subs and dubs'''
        # self.video_setting_button = QtWidgets.QPushButton(self.frame_2)
        # self.video_setting_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        # self.video_setting_button.setText("")
        # self.video_setting_button.setIconSize(QtCore.QSize(22, 22))
        # self.video_setting_button.setStyleSheet("QPushButton{image : url(icon_sets/video_setting/video_settings.png) }\n"
        #                                         )
        # self.video_setting_button.setObjectName("video_setting_button")
        # self.horizontalLayout_4.addWidget(self.video_setting_button)

        self.setting_button = QtWidgets.QPushButton(self.frame_2)
        self.setting_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.setting_button.setStyleSheet(
            "QPushButton{image : url(icon_sets/settings/settings.png) }\n")
        self.setting_button.setText("")
        self.setting_button.setObjectName("setting_button")
        self.horizontalLayout_4.addWidget(self.setting_button)

        self.Quality_box = QtWidgets.QComboBox(self.frame_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.Quality_box.sizePolicy().hasHeightForWidth())
        self.Quality_box.setSizePolicy(sizePolicy)
        self.Quality_box.setStyleSheet(
            "QComboBox\n"
            "    {\n"
            "	border-image :url(icon_sets/quality/border.png);\n"
            "    color: #fcffff;\n"
            "    font-size: 8pt;\n"
            "    font-weight: bold;\n"
            #    "    width: 41px;\n"
            "    background-color: #000000;\n"
            "    }\n"
            "    QComboBox QAbstractItemView \n"
            "    {\n"
            "    background: #fcffff;\n"
            "    border: 2px solid darkgray;\n"
            "    selection-background-color: #000000;\n"
            "    }\n"
            "QComboBox::drop-down {\n"
            "    border: 0px;\n"
            "    subcontrol-origin: padding;\n"
            "    subcontrol-position: top right;\n"
            "\n"
            "    border-top-right-radius: 3px;\n"
            "    border-bottom-right-radius: 3px;\n"
            "}\n")
        self.Quality_box.setIconSize(QtCore.QSize(0, 0))
        self.Quality_box.setDuplicatesEnabled(False)
        self.Quality_box.setObjectName("comboBox")
        self.Quality_box.addItem("     -")
        self.horizontalLayout_4.addWidget(self.Quality_box)

        self.volume_button = QtWidgets.QPushButton(self.frame_2)
        self.volume_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.volume_button.setText("")
        icon9 = QtGui.QIcon()
        icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume1.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.volume_button.setIcon(icon9)
        self.volume_button.setIconSize(QtCore.QSize(22, 22))
        self.volume_button.setCheckable(True)
        # self.volume_button.setFlat(True)
        self.volume_button.setObjectName("volume_button")
        self.horizontalLayout_4.addWidget(self.volume_button)

        self.volumeslider = VolSlider(self.frame_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.volumeslider.sizePolicy().hasHeightForWidth())
        self.volumeslider.setSizePolicy(sizePolicy)
        self.volumeslider.setAutoFillBackground(False)
        self.volumeslider.setStyleSheet(
            "QSlider::handle:horizontal \n"
            "    {\n"
            "    background: transparent;\n"
            "    width: 5px;\n"
            "    }\n"
            "QSlider::groove:horizontal {\n"
            "    border: 1px solid #444444;\n"
            "    height: 5px;\n"
            "    background: qlineargradient(y1: 0, y2: 1,stop: 0 grey, stop: 1.0 grey);\n"
            "}\n"
            " QSlider::sub-page:horizontal {\n"
            "    background:qlineargradient( y1: 0, y2: 1,\n"
            "        stop: 0 #42a6db, stop: 1 #0074e0); \n"
            "    border: 1px solid #777;\n"
            "    height: 5px;\n"
            "}\n"
            "QSlider::handle:horizontal:hover {\n"
            "    background: black;\n"
            "    height: 5px;\n"
            "    width: 5px;\n"
            "    border: 1px solid #0074e0;\n"
            "    }\n"
            "QSlider::sub-page:horizontal:disabled{background:qlineargradient( y1: 0, y2: 1,\n"
            "        stop: 0 #909090, stop: 1 #A8A8A8 );}\n"
            "")
        self.volumeslider.setOrientation(QtCore.Qt.Horizontal)
        self.volumeslider.setObjectName("volume_slider")
        self.horizontalLayout_4.addWidget(self.volumeslider)

        self.volume_percentage = QtWidgets.QLabel(self.frame_2)
        self.volume_percentage.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    font: 7pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "    }")
        self.volume_percentage.setObjectName("volume_status")
        self.volume_percentage.setMinimumWidth(35)
        self.volume_percentage.setText(" 75 %")
        self.horizontalLayout_4.addWidget(self.volume_percentage)

        self.verticalLayout.addWidget(self.frame_2)

        self.frame = QtWidgets.QFrame(self.mainFrame)
        font = QtGui.QFont()
        font.setFamily("Lucida Console")
        self.frame.setFont(font)
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.frame)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")

        sizegrip_2 = QtWidgets.QSizeGrip(Form)
        sizegrip_2.setStyleSheet("image:url(icon_sets/.png)")
        self.horizontalLayout_5.addWidget(
            sizegrip_2, 0, QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeft)

        # self.enter_url_label = QtWidgets.QLabel(self.frame)
        # font = QtGui.QFont()
        # font.setFamily("Arial Rounded MT Bold")
        # font.setPointSize(8)
        # font.setBold(False)
        # font.setItalic(False)
        # font.setWeight(50)
        # self.enter_url_label.setFont(font)
        # self.enter_url_label.setStyleSheet("QLabel\n"
        #                                    "    {\n"
        #                                    "    \n"
        #                                    "    font: 8pt \"Arial Rounded MT Bold\";\n"
        #                                    "    color: white;\n"
        #                                    "    border: 0px solid #076100;\n"
        #                                    "    }")
        # self.enter_url_label.setObjectName("enter_url_label")
        # self.horizontalLayout_5.addWidget(self.enter_url_label)

        self.url_box = QtWidgets.QComboBox(self.frame)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(200)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.url_box.sizePolicy().hasHeightForWidth())
        self.url_box.setSizePolicy(sizePolicy)
        self.url_box.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.url_box.setMouseTracking(False)
        self.url_box.setAcceptDrops(False)
        self.url_box.setWhatsThis("")
        self.url_box.setAccessibleDescription("")
        self.url_box.setAutoFillBackground(True)
        self.url_box.setStyleSheet("QComboBox\n"
                                   "    {\n"
                                   "    border: 2px solid #0074e0;\n"
                                   "    color: #fcffff;\n"
                                   "    font-size: 8pt;\n"
                                   "    font-weight: bold;\n"
                                   "    background-color: #000000;\n"
                                   "    border-radius: 6px;\n"
                                   "    }\n"
                                   "    QComboBox QAbstractItemView \n"
                                   "    {\n"
                                   "    background: #fcffff;\n"
                                   "    border: 2px solid darkgray;\n"
                                   "    selection-background-color: #000000;\n"
                                   "    }\n"
                                   "QComboBox::down-arrow {\n"
                                   "     image: url(icon_sets/url/url4.png)\n"
                                   "}\n"
                                   "QComboBox::drop-down {\n"
                                   "    subcontrol-origin: padding;\n"
                                   "    subcontrol-position: top right;\n"
                                   "    width: 20px;\n"
                                   " \n"
                                   "    border-top-right-radius: 3px;\n"
                                   "    border-bottom-right-radius: 3px;\n"
                                   "}")
        self.url_box.setInputMethodHints(QtCore.Qt.ImhUrlCharactersOnly)
        self.url_box.setEditable(True)
        self.url_box.setCurrentText("")
        self.url_box.setMaxVisibleItems(100)
        self.url_box.setMaxCount(100)
        self.url_box.setInsertPolicy(QtWidgets.QComboBox.InsertAtCurrent)
        self.url_box.setSizeAdjustPolicy(
            QtWidgets.QComboBox.AdjustToContentsOnFirstShow)
        self.url_box.setMinimumContentsLength(2)
        self.url_box.setIconSize(QtCore.QSize(20, 20))
        self.url_box.setDuplicatesEnabled(False)
        self.url_box.setFrame(True)
        self.url_box.setObjectName("url_box")
        self.horizontalLayout_5.addWidget(self.url_box)
        self.verticalLayout.addWidget(self.frame)

        sizegrip_1 = QtWidgets.QSizeGrip(Form)
        sizegrip_1.setStyleSheet(
            "image:url(icon_sets/size.png);width:15; height:18;")
        self.horizontalLayout_5.addWidget(
            sizegrip_1, 0, QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight)

        self.verticalLayout_2.addWidget(self.mainFrame)

        self.retranslateUi(Form)
        self.url_box.setCurrentIndex(-1)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Q-Stream Player"))
        self.Player_name.setText(_translate("Form", "Q-Stream Player"))
        self.time_status.setText(_translate("Form", "00:00:00"))
        self.backslash.setText(_translate("Form", "/"))
        self.duration_status.setText(_translate("Form", "00:00:00"))
        # self.enter_url_label.setText(_translate("Form", statusList[4]))

        # Set intial Volume
        self.volumeslider.setRange(0, 100)
        self.volumeslider.setValue(75)
        self.mediaPlayer.setVolume(75)
        self.position_slider.setRange(0, 100)

        # connecting buttons
        self.miniplayer_button.clicked.connect(self.setupMiniPlayer)
        self.position_slider.sliderMoved.connect(self.setPosition)
        self.position_slider.sliderMoved.connect(self.handleLabel)
        self.volume_button.clicked.connect(self.mute)
        self.volumeslider.valueChanged.connect(self.setVolume)
        self.screenshot_button.clicked.connect(self.screenshot)
        self.playback_button.clicked.connect(self.stopplayback)
        self.always_on_top_button.clicked.connect(self.checkOnTop)
        self.play_button.clicked.connect(self.play)
        self.open_File_button.clicked.connect(self.openFile)
        # self.video_setting_button.clicked.connect(self.handleQuality)
        self.setting_button.clicked.connect(self.handleSetting)
        self.Quality_box.currentTextChanged.connect(self.handleQuality)
        self.cross_button.clicked.connect(self.exit)
        self.maximize_button.clicked.connect(self.max)
        self.minimize_button.clicked.connect(self.min)

        # Shortcuts
        shortcut = QShortcut(QKeySequence('Esc'), self.video_playback)
        shortcut.activated.connect(self.EscFun)
        shortcut = QShortcut(QKeySequence('Space'), self.video_playback)
        shortcut.activated.connect(self.play)
        shortcut = QShortcut(QKeySequence('f'), self.video_playback)
        shortcut.activated.connect(self.fullscreen_video)
        shortcut = QShortcut(QKeySequence('c'), self.video_playback)
        shortcut.activated.connect(self.setupMiniPlayer)
        shortcut = QShortcut(QKeySequence('o'), self.video_playback)
        shortcut.activated.connect(self.openFile)
        shortcut = QShortcut(QKeySequence('a'), self.video_playback)
        shortcut.activated.connect(self.checkOnTop)
        shortcut = QShortcut(QKeySequence("Return"), self.video_playback)
        shortcut.activated.connect(self.playOnline)
        shortcut = QShortcut(QKeySequence('m'), self.video_playback)
        shortcut.activated.connect(self.mute)
        shortcut = QShortcut(QKeySequence(Qt.Key_Right), self.video_playback)
        shortcut.activated.connect(self.forwardSlider)
        shortcut = QShortcut(QKeySequence(Qt.Key_Left), self.video_playback)
        shortcut.activated.connect(self.backSlider)
        self.volupshortcut = QShortcut(QKeySequence(Qt.Key_Up),
                                       self.video_playback)
        self.volupshortcut.activated.connect(self.volumeUp)
        self.voldownshortcut = QShortcut(QKeySequence(Qt.Key_Down),
                                         self.video_playback)
        self.voldownshortcut.activated.connect(self.volumeDown)
        shortcut = QShortcut(QKeySequence(Qt.ControlModifier + Qt.Key_Right),
                             self.video_playback)
        shortcut.activated.connect(self.forwardSlider10)
        shortcut = QShortcut(QKeySequence(Qt.ControlModifier + Qt.Key_Left),
                             self.video_playback)
        shortcut.activated.connect(self.backSlider10)
        shortcut = QShortcut(QKeySequence(Qt.AltModifier + Qt.Key_Left),
                             self.video_playback)
        shortcut.activated.connect(self.backSlider5)
        shortcut = QShortcut(QKeySequence(Qt.AltModifier + Qt.Key_Right),
                             self.video_playback)
        shortcut.activated.connect(self.forwardSlider5)

        # loading history to Url Box
        items = self.load()
        self.url_box.addItems(items)
        self.url_box.setCurrentIndex(-1)

        # icon size
        # iconSize = QSize(5,5)
        # self.play_button.setIconSize(iconSize)
        # self.playback_button.setIconSize(iconSize)
        # self.screenshot_button.setIconSize(iconSize)
        # self.always_on_top_button.setIconSize(iconSize)
        # self.miniplayer_button.setIconSize(iconSize)
        # self.setting_button.setIconSize(iconSize)
        # self.volume_button.setIconSize(iconSize)

        # button size
        btnSize = QSize(22, 22)
        self.play_button.setMaximumSize(btnSize)
        self.playback_button.setMaximumSize(btnSize)
        self.screenshot_button.setMaximumSize(btnSize)
        self.always_on_top_button.setMaximumSize(btnSize)
        self.miniplayer_button.setMaximumSize(btnSize)
        # self.video_setting_button.setMaximumSize(btnSize)
        self.setting_button.setMaximumSize(btnSize)
        self.volume_button.setMaximumSize(btnSize)

        # set margin
        self.horizontalLayout.setContentsMargins(10, 5, 9, 0)
        self.horizontalLayout_4.setContentsMargins(9, 0, 9, 0)
        self.horizontalLayout_4.setSpacing(4)
        self.horizontalLayout_5.setContentsMargins(0, 5, 5, 5)
        self.horizontalLayout_6.setContentsMargins(9, 0, 9, 0)

        # Media player settings
        self.mediaPlayer.setVideoOutput(self.video_playback)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)

    def handleLabel(self):
        self.time_status.clear()
        mtime = QtCore.QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.time_status.setText(self.time.toString())

    def hide_all(self):
        self.frame_3.close()
        # self.frame.close()
        self.url_box.close()
        self.playback_button.close()
        self.screenshot_button.close()
        self.Quality_box.close()
        self.volume_button.close()
        # self.video_setting_button.close()
        # self.setting_button.close()

    def show_all(self):
        self.frame_3.show()
        # self.frame.show()
        self.url_box.show()
        self.playback_button.show()
        self.screenshot_button.show()
        self.Quality_box.show()
        self.volume_button.show()
        # self.video_setting_button.show()
        self.setting_button.show()

    def checkOnTop(self):
        self.isOnTop = not self.isOnTop
        if self.isOnTop:
            self.always_on_top_button.setProperty("top", True)
            self.always_on_top_button.setStyle(
                self.always_on_top_button.style())
            Form.setWindowFlags(Form.windowFlags()
                                | QtCore.Qt.WindowStaysOnTopHint)
        else:
            self.always_on_top_button.setProperty("top", False)
            self.always_on_top_button.setStyle(
                self.always_on_top_button.style())
            Form.setWindowFlags(Form.windowFlags()
                                & ~QtCore.Qt.WindowStaysOnTopHint)
        Form.show()

    def miniProperty(self):
        self.video_playback.setMinimumSize(QSize(200, 100))
        self.video_playback.resize(QSize(550, 270))
        Form.resize(QSize(550, 270))
        Form.setMinimumSize(QSize(200, 175))
        self.mainFrame.setMinimumSize(QSize(200, 60))
        self.mainFrame.resize(QSize(200, 53))

    def standardProperty(self):
        self.video_playback.setMinimumSize(QSize(200, 100))
        self.mainFrame.setMinimumSize(QSize(200, 82))
        Form.setMinimumSize(QSize(200, 202))
        Form.resize(550, 369)

    def setupMiniPlayer(self):
        self.isMini = not self.isMini
        if self.isMini:
            self.miniplayer_button.setProperty("mini", True)
            self.miniplayer_button.setStyle(self.miniplayer_button.style())
            self.hide_all()
            self.miniProperty()

        else:
            self.miniplayer_button.setProperty("mini", False)
            self.miniplayer_button.setStyle(self.miniplayer_button.style())
            self.standardProperty()

            self.show_all()

    def load(self):
        scorefile = "db.bat"
        if os.path.exists(scorefile):
            with open(scorefile, 'rb') as sf:
                scores = pickle.load(sf)
        else:
            scores = []

        with open(scorefile, "wb") as sf:
            pickle.dump(scores, sf)
        return scores

    def scor_func(self, url):
        scorefile = "db.bat"
        if os.path.exists(scorefile):
            with open(scorefile, 'rb') as sf:
                scores = pickle.load(sf)
        else:
            scores = []
        scores.append(url)

        with open(scorefile, "wb") as sf:
            if len(scores) > 100:
                print("here", scores)
                scores = scores[1:]
            pickle.dump(scores, sf)
        return scores

    def mute(self):
        if self.mediaPlayer.isMuted():
            print('[ ! Full Volume]')
            self.mediaPlayer.setMuted(False)
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume1.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)
            self.volume_button.setIconSize(QSize(22, 22))
            self.volumeslider.setEnabled(True)
            # shortcut Enable
            self.volupshortcut.setEnabled(True)
            self.voldownshortcut.setEnabled(True)

        else:
            print('[ ! Mute Volume]')
            self.mediaPlayer.setMuted(True)
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume2.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)
            self.volume_button.setIconSize(QSize(22, 22))
            self.volumeslider.setEnabled(False)
            # shrotcut disable
            self.volupshortcut.setEnabled(False)
            self.voldownshortcut.setEnabled(False)

    def play(self):
        if self.mediaPlayer.isVideoAvailable():
            if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
                print("[ ! PAUSE PRESSED ]")
                self.mediaPlayer.pause()
            else:
                print("[ ! PLAY PRESSED ]")
                self.mediaPlayer.play()

    def playOnline(self):
        if self.url_box.currentText() != '':
            print('[ ! GETTING VIDEO ONLINE ]')
            fileName = self.url_box.currentText()
            res = requests.get('https://mediaplayerserver.herokuapp.com/',
                               params={"key": fileName})
            try:
                self.streams = json.loads(res.text)
                try:
                    self.mediaPlayer.setMedia(
                        QMediaContent(QUrl(self.streams['best'])))
                    self.play_video()
                    self.isOnline = True
                    self.addQuality()
                    if self.url_box.findText(fileName, Qt.MatchExactly) < 0:
                        self.url_box.addItem(fileName)
                        self.scor_func(fileName)
                except KeyError:
                    print("[ ! Error Video Not Supported By platform]")
            except json.JSONDecodeError:
                print("[ ! Error NoPluginError]")
            finally:
                self.url_box.setCurrentText("")

    def openFile(self):
        print('[ ! OPEN FILE ]')
        username = getpass.getuser()
        if sys.platform == 'win32':
            path = 'C:/Users/' + username + '/Videos/'
        elif sys.platform == 'linux' or sys.platform == 'Darwin':
            path = '/home/' + username + '/Videos/'

        formats = str.join(' ', [
            '*.%s' % str(fmt).strip('b').strip("'")
            for fmt in QtGui.QMovie.supportedFormats()
        ])

        fileName, _ = QFileDialog.getOpenFileName(
            self.video_playback, "Select media file", path,
            "Video Files (*.mp4 *.flv *.ts *.mts *.avi *.mkv)")
        if fileName != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.play_video()

    # def decodeLink(self,url):
    #     try:
    #         streams = streamlink.streams(url)
    #         keys = [k for k in streams.keys()]
    #         data = dict()
    #         for k in keys:
    #             data[k] = streams[k].url
    #         return data

    #     except streamlink.NoPluginError:
    #         return None

    # def playOnline(self):
    #         if self.url_box.currentText() != '':
    #             print('[ ! GETTING VIDEO ONLINE ]')
    #             fileName = self.url_box.currentText()
    #             self.streams = self.decodeLink(fileName)
    #             try:
    #                 self.mediaPlayer.setMedia(QMediaContent(QUrl(self.streams['best'])))
    #                 self.play_video()
    #                 self.isOnline = True
    #                 self.addQuality()
    #                 if self.url_box.findText(fileName, Qt.MatchExactly) < 0:
    #                     self.url_box.addItem(fileName)
    #                     self.scor_func(fileName)
    #             except KeyError:
    #                 print("[ ! Error Video Not Supported By platform]")
    #             finally:
    #                 self.url_box.setCurrentText("")

    def play_video(self):
        print('[ ! PLAYING VIDEO ]')
        self.play_button.setEnabled(True)
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        print('[ ! CHANGING MEDIA STATE ]')
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.play_button.setProperty('play', False)
            self.play_button.setStyle(self.play_button.style())
        else:
            self.play_button.setProperty('play', True)
            self.play_button.setStyle(self.play_button.style())

    def stopplayback(self):
        print('[ ! STOP PLAYBACK VIDEO ]')
        self.mediaPlayer.stop()
        self.play_video()

    def positionChanged(self, position):
        print('[ ! POSITION CHANGED ]')
        self.position_slider.setValue(position)

    def durationChanged(self, duration):
        print('[ ! DURATION CHANGED ]')
        self.position_slider.setRange(0, duration)
        self.duration_status.clear()
        mtime = QtCore.QTime(0, 0, 0, 0)
        time = mtime.addMSecs(self.mediaPlayer.duration())
        self.duration_status.setText(time.toString())

    def setPosition(self, position):
        print('[ ! POSITION SET ]')
        self.mediaPlayer.setPosition(position)

    def setVolumePos(self, remain):
        print('[ ! REMANING VOLUME ]')
        print(remain)
        self.volumeslider.setRange(remain, 100)

    def setVolume(self, vol):
        print('[ ! SET VOLUME ]')
        print("set volume  = " + str(vol))
        if vol >= 0 and vol <= 100:
            self.volume_percentage.setText(" " + str(vol) + " %")
        if vol <= 0:
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume2.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)
        else:
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume1.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)

        self.volumeslider.setValue(vol)
        self.mediaPlayer.setVolume(vol)

    def screenshot(self):

        print('[ ! SCREENSHOT ]')
        wincen = Form.geometry()
        topX = wincen.topLeft().x()
        topY = wincen.topLeft().y()
        geo = self.video_playback.geometry()
        image = pyautogui.screenshot(region=(topX, topY + 38, geo.width(),
                                             geo.height() - 35))

        filename = "screenshot" + str(uuid.uuid4()) + ".png"
        username = getpass.getuser()

        if sys.platform == 'win32':
            path = 'C:/Users/' + username + '/Pictures/' + filename
        elif sys.platform == 'linux' or sys.platform == 'Darwin':
            path = '/home/' + username + '/Pictures/' + filename
        image.save(path)

    def EscFun(self):
        if self.video_playback.isFullScreen():
            Form.show()
            self.video_playback.setFullScreen(False)

    def fullscreen_video(self):
        if self.mediaPlayer.isVideoAvailable():
            if self.video_playback.isFullScreen():
                self.video_playback.setFullScreen(False)
                print('[ ! Normal Screen ]')
                Form.show()
            else:
                print('[ ! Full Screen ]')
                self.video_playback.setFullScreen(True)
                Form.hide()

    def getFormat(self):
        li = [k for k in self.streams.keys()]
        for q in li:
            if q.startswith('audio'):
                li.remove(q)
                try:
                    li.remove('audio_opus')
                except ValueError:
                    pass
        return li

    def changeQuality(self, quality):
        pos = self.mediaPlayer.position()
        try:
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl(self.streams[quality])))
        except KeyError:
            pass
        self.setPosition(pos)
        self.mediaPlayer.play()

    def handleSetting(self):
        from setting import SettingDialog
        dlg = SettingDialog()
        dlg.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        dlg.exec_()

    def addQuality(self):
        self.Quality_box.clear()
        self.Quality_box.addItems(self.getFormat())

    def handleQuality(self):
        if self.isOnline:
            self.changeQuality(self.Quality_box.currentText())

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000)

    def forwardSlider5(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 5000)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000)

    def backSlider5(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 5000)

    def volumeUp(self):
        self.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def max(self):
        if not Form.isMaximized():
            print("[! Window is Maximized]")
            Form.showMaximized()
        else:
            print("[! Window is Normal]")
            Form.showNormal()

    def min(self):
        if not Form.isMinimized():
            print("[! Window is Minimized]")
            Form.showMinimized()
        else:
            print("[! Window is Normal]")
            Form.showNormal()

    def exit(self):
        self.mediaPlayer.stop()
        sys.exit()
Ejemplo n.º 40
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)
Ejemplo n.º 41
0
class VideoPlayer(QWidget):
    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute(Qt.WA_NoSystemBackground, True)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)

        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        #        self.lbl.setDisabled(False)
        self.lbl.setFixedWidth(60)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        #        self.elbl.setDisabled(True)
        self.elbl.setFixedWidth(60)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handleLabel)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(5, 0, 5, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \
    "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \
    "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes"

        self.widescreen = True

        if aPath is not None:
            self.loadFilm(aPath)

#### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)
        self.shortcut = QShortcut(QKeySequence("o"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(" "), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence("f"), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(
            QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left),
                                  self)
        self.shortcut.activated.connect(self.backSlider10)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        print("QT5 Player started")

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "Open Movie", QDir.homePath(),
            "Videos (*.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v)")

        if fileName != '':
            self.loadFilm(fileName)
            print("File loaded")

    def playFromURL(self):
        self.mediaPlayer.pause()
        clip = QApplication.clipboard()
        myurl = clip.text()
        if myurl.startswith("http"):
            self.mediaPlayer.setMedia(QMediaContent(QUrl(myurl)))
        else:
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(myurl)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(myurl)

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: " + self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        print("Goodbye ...")
        app.quit()

    def contextMenuRequested(self, point):
        menu = QtWidgets.QMenu()
        actionFile = menu.addAction("open File (o)")
        actionclipboard = menu.addSeparator()
        actionURL = menu.addAction("URL / File from Clipboard (u)")
        actionclipboard = menu.addSeparator()
        actionToggle = menu.addAction("show / hide Slider (s)")
        actionFull = menu.addAction("Fullscreen (f)")
        action169 = menu.addAction("16 : 9")
        action43 = menu.addAction("4 : 3")
        actionSep = menu.addSeparator()
        actionInfo = menu.addAction("Info (i)")
        action5 = menu.addSeparator()
        actionQuit = menu.addAction("Exit (q)")

        actionFile.triggered.connect(self.openFile)
        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        action169.triggered.connect(self.screen169)
        action43.triggered.connect(self.screen43)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.33)

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def handleFullscreen(self):
        if self.windowState() & QtCore.Qt.WindowFullScreen:
            self.showNormal()
            print("no Fullscreen")
        else:
            self.showFullScreen()
            print("Fullscreen entered")

    def handleInfo(self):
        msg = QMessageBox()
        msg.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
                           | Qt.SplashScreen)
        msg.setGeometry(self.frameGeometry().left() + 30,
                        self.frameGeometry().top() + 30, 300, 400)
        msg.setIcon(QMessageBox.Information)
        msg.setText("QT5 Player")
        msg.setInformativeText(self.myinfo)
        msg.setStandardButtons(QMessageBox.Close)
        msg.exec()

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def showSlider(self):
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.55)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() \
      - QPoint(self.frameGeometry().width() / 2, \
      self.frameGeometry().height() / 2))
            event.accept()

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        f = str(event.mimeData().urls()[0].toLocalFile())
        self.loadFilm(f)

    def loadFilm(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        print(self.mediaPlayer.media().canonicalResource().resolution())

    def openFileAtStart(self, filelist):
        matching = [s for s in filelist if ".myformat" in s]
        if len(matching) > 0:
            self.loadFilm(matching)

##################### update Label ##################################

    def handleLabel(self):
        self.lbl.clear()
        mtime = QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())
Ejemplo n.º 42
0
class Main(QWidget):
    """主窗口。"""
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        # 信息。
        self.result = {'uid': 0}
        # 歌单歌曲id。
        self.playurl = {}
        # 搜索歌曲id。
        self.ids = {}
        # 本地音乐地址。
        self.local_url = {}
        # 歌曲图片。
        self.pictures = {}
        # 歌曲列表id们。
        self.playids = {}

        self.setObjectName('Main')
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setWindowTitle('NetEase')
        self.setWindowIcon(QIcon('icons/format.ico'))
        # 功能。
        self.function = api.WebApi()
        # 主页及其他功能。
        self.index = Index(self)
        self.current_list = SongsWindow(self)
        # -------
        # 待改进。
        self.resize(1000, 650)
        # 按钮start.
        self.btn_exit = QPushButton(self)
        self.btn_min = QPushButton(self)
        self.btn_max = QPushButton(self)
        self.btn_login = QPushButton("Unlogin", self)
        self.btn_search = QPushButton(self)
        self.find_music = QPushButton(self)
        self.locale_music = QPushButton(self)
        self.select_path = QPushButton(self)
        self.play = QPushButton(self)
        self.stop = QPushButton(self)
        self.nextSong = QPushButton(self)
        self.beforeSong = QPushButton(self)
        self.pause = QPushButton(self)
        self.btn_list = QPushButton(self)
        self.add_all_song = QPushButton(self)
        self.single = QPushButton(self)
        self.cycle = QPushButton(self)
        self.loop_flags = True
        # 按钮end.
        # -------
        # 标签start.
        self.lbe_pic = QLabel(self)
        self.header_hr = QLabel(self)
        self.header_icon = QLabel(self)
        self.header_text = QLabel(self)
        self.spacing = QLabel(self)
        self.spacing2 = QLabel(self)
        self.spacing3 = QFrame()
        self.spacing4 = QFrame()
        self.songs_list = QLabel(self)
        self.song_pic = QLabel(self)
        self.time1 = QLabel(self)
        self.time2 = QLabel(self)
        self.song_name = QLabel(self)
        # 歌单内的信息。
        self.detail_pic = QLabel(self)
        self.detail_pic.hide()
        self.detail_author = QLabel(self)
        self.detail_author.hide()
        self.detail_tag = QLabel(self)
        self.detail_tag.hide()
        self.detail_name = QLabel(self)
        self.detail_name.hide()
        self.detail_description = QLabel(self)
        self.detail_description.hide()
        # 标签end.
        # -------
        # 输入框start.
        self.search_line = QLineEdit(self)
        # 输入框end.
        # -------
        # 列表框start.
        self.playlist = PlayList(self)
        # 列表框end.
        # -------
        # 表格start.
        self.table = QTableWidget(self)
        self.table.setObjectName("tablelist")
        #   表格连接信号.
        self.table.itemDoubleClicked.connect(self.add_song)
        self.table.itemDoubleClicked.connect(self.play_song)
        self.table.hide()
        # 表格end.
        # -------
        # 滚动条start。
        self.slider = QSlider(self)
        # 滚动条end.
        # -------
        # 播放功能。
        self.player = QMediaPlayer()
        # -------
        # 布局与属性设置。
        self.mainLayout = QGridLayout()
        self.topLayout = QHBoxLayout()
        self.leftLayout = QVBoxLayout()
        self.centerLayout = QHBoxLayout()
        self.rightLayout = QVBoxLayout()
        self.rightLayout1 = QHBoxLayout()
        self.rightLayout2 = QVBoxLayout()
        self.rightLayout21 = QHBoxLayout()
        self.bottomLayout = QHBoxLayout()
        self.bottomLayout1 = QVBoxLayout()
        self.playLayout = QHBoxLayout()
        self.set_buttons()
        self.set_labels()
        self.set_lines()
        self.set_sliders()
        self.set_medias()
        # -------
        # 其他功能。
        self.load_login()
        self.manager = QNetworkAccessManager()
        self.setLayout(self.set_layouts())

    # 登陆部分start.
    def lwindow(self):
        """
            登陆框。
        """
        login = LoginWindow(self)
        login.exec_()

    def load_login(self):
        """
            查看是否已经登陆。
        """
        os.chdir('.' + '/data' + '/cookies')
        filedir = os.listdir('.')
        if filedir:
            try:
                with open(filedir[0], 'r') as f:
                    content = f.readlines()
                    self.result['uid'] = content[1][:-1]
                    # 读入当前用户uid.
                    self.btn_login.setText(content[0][:-1])
                    # 加载昵称。
                    self.btn_login.disconnect()
                    self.btn_login.clicked.connect(self.quit_login)
                    # 改变登陆按钮连接到退出功能。
                    with open(filedir[-1], 'rb') as fi:
                        p3 = QPixmap()
                        p3.loadFromData(QByteArray(fi.read()))
                        self.lbe_pic.setStyleSheet("border: 0px;")
                        # 发现圆角只是边框,图片并不变化。
                        self.lbe_pic.setPixmap(p3.scaled(40, 40))
                    # 加载头像。
                self.btn_login.setToolTip("登出")
            except:
                pass
        else:
            pass
        os.chdir('..')
        os.chdir('..')
        try:
            self.playlist.set_list()
        except:
            pass

    def quit_login(self):
        """
            退出登陆。
        """
        self.set_labels()
        self.lbe_pic.setStyleSheet("")
        self.btn_login.setText("Unlogin")
        self.btn_login.disconnect()
        self.btn_login.clicked.connect(self.lwindow)
        self.playlist.disconnect()
        self.playlist.clear()
        shutil.rmtree('data/cookies')
        os.makedirs('.' + '/data' + '/cookies')
    # 登陆部分end.

    # 内置组件部分start.

    def set_buttons(self):
        """
            全部的按钮组件。
        """
        # 退出。
        self.btn_exit.setObjectName('exit')
        self.btn_exit.setText('×')
        self.btn_exit.clicked.connect(self.close)
        self.btn_exit.setToolTip('退出')
        # 最小化。
        self.btn_min.setObjectName('mini')
        self.btn_min.setText('-')
        self.btn_min.clicked.connect(self.showMinimized)
        self.btn_min.setToolTip('最小化')
        # 最大化。
        self.btn_max.setObjectName('maxi')
        self.btn_max.setText('□')
        self.btn_max.setToolTip('^_^此功能已上火星')
        # 登陆。
        self.btn_login.setObjectName('login')
        self.btn_login.clicked.connect(self.lwindow)
        self.btn_login.setToolTip('登陆')
        # 搜索。
        self.btn_search.setObjectName('searchBtn')
        self.btn_search.resize(48, 48)
        self.btn_search.clicked.connect(self.song_search)
        # 发现音乐。
        self.find_music.setObjectName('find')
        self.find_music.setIcon(QIcon('icons/music.png'))
        self.find_music.setText("发现音乐")
        self.find_music.clicked.connect(self.show_index)
        # 本地音乐。
        self.locale_music.setObjectName('locale')
        self.locale_music.setIcon(QIcon('icons/music.png'))
        self.locale_music.setText("本地音乐")
        self.locale_music.clicked.connect(self.looking_music)
        self.select_path.setObjectName('selection')
        self.select_path.clicked.connect(self.set_path)
        self.select_path.setText("选择目录")
        self.select_path.hide()
        # 播放页。
        self.play.setObjectName('play')
        self.play.setToolTip("播放歌曲")
        self.play.clicked.connect(self.play_song)
        self.stop.setObjectName('stop')
        self.stop.setToolTip("停止播放")
        self.stop.clicked.connect(self.stop_song)
        self.nextSong.setObjectName('next')
        self.nextSong.setToolTip("下一首歌曲")
        self.nextSong.clicked.connect(self.next_song)
        self.beforeSong.setObjectName('before')
        self.beforeSong.setToolTip("上一首歌曲")
        self.beforeSong.clicked.connect(self.before_song)
        self.pause.setObjectName("pause")
        self.pause.setToolTip("暂停播放")
        self.pause.hide()
        self.pause.clicked.connect(self.pause_song)
        self.single.setObjectName('single')
        self.single.setToolTip('单曲循环')
        self.single.clicked.connect(self.set_modles)
        self.single.hide()
        self.cycle.setObjectName('cycle')
        self.cycle.setToolTip('循环播放')
        self.cycle.clicked.connect(self.set_modles)
        # 歌曲列表。
        self.btn_list.setObjectName('songslist')
        self.btn_list.clicked.connect(self.songs_lists)
        # 歌单内功能。
        self.add_all_song.setObjectName("addbutton")
        self.add_all_song.setText("播放全部")
        self.add_all_song.clicked.connect(self.add_all)
        self.add_all_song.hide()

    def set_labels(self):
        """
            全部的标签组件。
        """
        p = QPixmap()
        p.load('icons/unlogin.png')
        p2 = QPixmap()
        p2.load('icons/format_2.png')
        # 头部装饰start。
        self.lbe_pic.setObjectName("headpic")
        self.lbe_pic.setPixmap(p.scaled(40, 40))
        self.header_hr.setObjectName('Headerhr')
        self.header_hr.setText("推荐")
        self.header_icon.setObjectName('HIcon')
        self.header_icon.setPixmap(p2.scaled(50, 50))
        self.header_text.setObjectName('HText')
        self.header_text.setText(" Music")
        # 头部装饰end。
        # 头部竖线装饰start。
        self.spacing.setObjectName('spacing1')
        self.spacing.resize(50, 50)
        self.spacing2.setObjectName('spacing2')
        self.spacing2.resize(50, 50)
        # 头部竖线装饰end。
        self.songs_list.setObjectName("songlist")
        self.songs_list.setText("我的音乐")
        # 歌单标签设置start。
        self.detail_pic.setObjectName("pic")
        self.detail_author.setObjectName("author")
        self.detail_tag.setObjectName("tag")
        self.detail_name.setObjectName("name")
        self.detail_description.setObjectName("description")
        # 歌单标签设置end。
        # 歌曲图片。
        self.song_pic.setObjectName("songpic")
        p3 = QPixmap()
        p3.load('icons/nosong.png')
        self.song_pic.setPixmap(p3)
        # 时间显示组件。
        self.time1.setObjectName("time1")
        self.time1.setText('00:00')
        self.time1.setAlignment(Qt.AlignCenter | Qt.AlignRight | Qt.AlignBottom)
        self.time2.setObjectName("time2")
        self.time2.setText('00:00')
        self.time2.setAlignment(Qt.AlignBottom)
        # 间隔装饰。
        self.spacing3.setFrameShape(QFrame.VLine)
        self.spacing3.setFrameShadow(QFrame.Plain)
        self.spacing3.setLineWidth(2)
        self.spacing4.setFrameShape(QFrame.HLine)
        self.spacing3.setFrameShadow(QFrame.Plain)
        self.spacing3.setLineWidth(2)
        # 歌曲名字。
        self.song_name.setObjectName("songname")
        self.song_name.setAlignment(Qt.AlignCenter)
        self.song_name.setText("~~~还没有歌曲呦~~~")

    def set_lines(self):
        """
            输入框。
        """
        self.search_line.setObjectName('SearchLine')
        self.search_line.setPlaceholderText('搜索音乐。')

    def set_sliders(self):
        """
            滚动组件。
        """
        self.slider.setObjectName("slider")
        self.slider.setOrientation(Qt.Horizontal)
        self.slider.sliderMoved.connect(self.slider_media)
        self.slider.sliderReleased.connect(self.slider_setdone)
    # 内置组件备份end.

    # 歌曲部分start.

    #  框架,播放器及功能的处理。
    def set_tables(self):
        """
            表格呈现歌单详细信息。
        """
        self.table.setColumnCount(6)
        self.table.setHorizontalHeaderLabels([' ', '操作', '音乐', '歌手', '专辑', '时长'])
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 设置列宽。
        self.table.setColumnWidth(0, 40)
        self.table.setColumnWidth(1, 40)
        self.table.setColumnWidth(2, 360)
        self.table.setColumnWidth(3, 140)
        self.table.setColumnWidth(4, 140)
        self.table.setColumnWidth(5, 60)
        # 设置充满表宽。
        self.table.horizontalHeader().setStretchLastSection(True)
        # 设置表头亮度。
        self.table.horizontalHeader().setHighlightSections(False)
        # 设置每次选择为一行。
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        # 设置垂直表头不显示。
        self.table.verticalHeader().setVisible(False)

    def set_medias(self):
        """
            设置播放器。
        """
        self.player.setVolume(100)
        self.player.stateChanged.connect(self.loop)
        self.player.positionChanged.connect(self.set_time)

    def song_search(self):
        """
            搜索功能。
            name: 歌曲名称。
            id: 歌曲id。
            artists: [0][1]['name']歌曲作者可能不止一人,['img1v1Url']作者头像。
            album: ['name']专辑名称。
        """ 
        # 暂时只做一页。翻页属后续功能。
        text = self.search_line.text()
        if text:
            self.set_tables()
            self.hide_index()
            details = self.function.search(text)
            try:
                # 搜到没有的情况。
                songs = details['songs']
            except KeyError:
                self.table.hide()
                self.detail_description.setText('〖很抱歉,木有此歌曲〗')
                return
            songcount = details['songCount']
            if songcount > 100:
                count = 100
            else:
                count = songcount
            self.table.setRowCount(count)
            for i in range(count):
                self.ids[str(i)] = songs[i]['id']
                self.table.setItem(i, 0, QTableWidgetItem(str(i)))

                self.table.setItem(i, 1, QTableWidgetItem(QIcon('icons/playlist.png'), ''))

                self.table.setItem(i, 2, QTableWidgetItem(songs[i]['name']))

                people = ','.join([c['name'] for c in songs[i]['artists']])
                self.table.setItem(i, 3, QTableWidgetItem(people))

                self.table.setItem(i, 4, QTableWidgetItem(songs[i]['album']['name']))

                minuties = songs[i]['duration'] // 60000
                seconds = songs[i]['duration'] // 1000 % 60
                time = QTime(0, minuties, seconds)
                self.table.setItem(i, 5, QTableWidgetItem(time.toString("mm:ss")))
        else:
            return

        # 加载图片。
        pic = QPixmap()
        pic.load('icons/search2.jpg')
        self.detail_pic.setPixmap(pic.scaled(200, 200))
        self.detail_name.setText('遨游在音乐的天空。')
        self.detail_author.setText("It's my sky!")
        self.detail_tag.setText('『Music, music』')
        self.detail_description.setText('〖Search Result〗')

    def show_playlist(self, name):
        """
            显示歌单详细信息。
            trackCount: 总数。
            name: 歌单名称。
            tags: 歌单标签。
            coverImgUrl: 歌单图片。
            creator: ['nickname'] 创建者名字。
            description: 歌单简介。
            tracks: 歌曲总列表[]
            ,['bMusic']['id']歌曲id,['name']歌曲名称
            , ['mp3Url']歌曲地址
            , ['artists'][0]['name']歌曲作者,['id']作者id
            , ['album']['name']专辑名称,['blurPicUrl']图片。
        """
        self.set_tables()
        self.hide_index()
        details = self.function.details_playlist(self.result[name.replace('\n', '')])
        self.table.setRowCount(details['trackCount'])
        # 加载在表格里。
        for i in range(len(details['tracks'])):
            if not details['tracks'][i]['bMusic']['name']:
                self.playurl[str(i)] = details['tracks'][i]['id']
                self.pictures[str(i)] = details['tracks'][i]['album']['blurPicUrl']
            else:
                self.playurl[details['tracks'][i]['bMusic']['name']] = details['tracks'][i]['id']
                self.pictures[details['tracks'][i]['bMusic']['name']] = details['tracks'][i]['album']['blurPicUrl']
            # 设置序号。
            self.table.setItem(i, 0, QTableWidgetItem(str(i)))

            self.table.setItem(i, 1, QTableWidgetItem(QIcon('icons/playlist.png'), ''))

            if not details['tracks'][i]['bMusic']['name']:
                self.table.setItem(i, 2, QTableWidgetItem(str(i)))
            else:
                self.table.setItem(i, 2, QTableWidgetItem(details['tracks'][i]['bMusic']['name']))

            people = ','.join([t['name'] for t in details['tracks'][i]['artists']])
            self.table.setItem(i, 3, QTableWidgetItem(people))

            self.table.setItem(i, 4, QTableWidgetItem(details['tracks'][i]['album']['name']))

            minuties = details['tracks'][i]['bMusic']['playTime'] // 60000
            seconds = details['tracks'][i]['bMusic']['playTime'] // 1000 % 60
            time = QTime(0, minuties, seconds)
            self.table.setItem(i, 5, QTableWidgetItem(time.toString("mm:ss")))
        # 加载歌单图片。
        self.manager.clearAccessCache()
        pic = self.manager.get(QNetworkRequest(QUrl(details['coverImgUrl'])))
        self.manager.finished.connect(lambda: load_pic(pic))

        def load_pic(picture):
            p4 = QPixmap()
            p4.loadFromData(picture.readAll())
            self.detail_pic.setPixmap(p4.scaled(200, 200))
        # 加载歌单名称,创建者,标签,简介。
        self.detail_name.setText('::======>>歌单: ' + details['name'])
        self.detail_author.setText('Creator: ' + details['creator']['nickname'])
        self.detail_tag.setText('『' + str(details['tags'])[1:-1] + '』')
        try:
            self.detail_description.setText('〖' + details['description'] + '〗')
            self.detail_description.setWordWrap(True)
        except TypeError:
            self.detail_description.setText('〖〗')

    #    歌曲组件start。

    def set_song(self, name, author):
        """
            设置歌曲链接连接。
        """
        try:
            self.manager.disconnect()
        except TypeError:
            pass
        self.manager.clearAccessCache()
        try:
            self.player.setMedia(QMediaContent(QUrl(self.function.details_search(self.playids[name][author]))))
            data = self.manager.get(QNetworkRequest(QUrl(self.pictures[name])))
            self.manager.finished.connect(lambda: self.load(data))
        except KeyError:
            self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.playids[name][author])))

    def add_song(self):
        """
            将歌曲加入到播放列表。
        """
        name = self.table.item(self.table.currentRow(), 2).text()
        author = self.table.item(self.table.currentRow(), 3).text()
        times = self.table.item(self.table.currentRow(), 5).text()
        content = author + ' - ' + name + ' - ' + times
        for i in range(self.current_list.count()):
            if self.current_list.item(i).text() == content:
                if self.current_list.currentItem().text() == content:
                    break
                else:
                    self.current_list.setCurrentRow(i)
                    self.set_song(name, author)
                    break
        else:
            self.current_list.addItem(content)
            self.current_list.setCurrentRow(self.current_list.count()-1)
            try:
                self.playids[name]
            except KeyError:
                self.playids[name] = {}
                try:
                    self.playids[name][author] = self.playurl[name]
                except KeyError:
                    self.playids[name][author] = self.ids[str(self.table.currentRow())]
            self.set_song(name, author)
        # 将列表保存到文件夹下。
        with open('data/music/' + content.replace(':', '.'), 'w') as f:
            try:
                f.write(self.pictures[name])
            except KeyError:
                pass

    def add_all(self):
        """
            将表格中所有的歌曲添加到播放列表。
        """
        for i in reversed(range(self.table.rowCount())):
            name = self.table.item(i, 2).text()
            author = self.table.item(i, 3).text()
            times = self.table.item(i, 5).text()
            content = name + ' - ' + author + ' - ' + times
            temp = [self.current_list.item(j).text() for j in range(self.current_list.count())]
            if content in temp:
                pass
            else:
                self.current_list.addItem(content)
                self.playids[name] = {}
                try:
                    self.playids[name][author] = self.playurl[name]
                except KeyError:
                    self.playids[name][author] = self.ids[str(self.table.currentRow())]
            with open('data/music/' + content.replace(':', '.'), 'w') as f:
                try:
                    f.write(self.pictures[name])
                except KeyError:
                    pass
        self.set_song(name, author)
        self.play_song()

    def play_song(self):
        """
            播放组件。
        """
        # BUG: 用isAudio判断是否为有效音频是特么的双击居然显示无效。
        try:
            self.song_name.setText(self.current_list.currentItem().text().split(' - ')[1])
            self.time2.setText(self.current_list.currentItem().text().split(' - ')[2])
            self.player.play()
            self.play.hide()
            self.pause.show()
        except AttributeError:
            return

    def pause_song(self):
        """
            暂停组件。
        """
        self.player.pause()
        self.pause.hide()
        self.play.show()

    def stop_song(self):
        """
            停止组件。
        """
        self.player.stop()
        self.pause.hide()
        self.play.show()

    def next_song(self):
        """
            下一首,若到头了则播放当前。
        """
        try:
            self.manager.disconnect()
        except TypeError:
            pass
        self.manager.clearAccessCache()
        try:
            content = self.current_list.item(self.current_list.currentRow()+1).text().split(' - ')
            self.song_name.setText(content[1])
            self.time2.setText(content[2])
            self.player.setMedia(QMediaContent(QUrl(self.function.details_search(self.playids[content[1]][content[0]]))))
            data = self.manager.get(QNetworkRequest(QUrl(self.pictures[content[1]])))
            self.manager.finished.connect(lambda: self.load(data))
            self.current_list.setCurrentRow(self.current_list.currentRow()+1)
            self.player.play()
        except AttributeError:
            self.player.play()

    def before_song(self):
        """
            前一首,若到头则播放当前。
        """
        try:
            self.manager.disconnect()
        except TypeError:
            pass
        self.manager.clearAccessCache()
        try:
            content = self.current_list.item(self.current_list.currentRow()-1).text().split(' - ')
            self.song_name.setText(content[1])
            self.time2.setText(content[2])
            self.player.setMedia(QMediaContent(QUrl(self.function.details_search(self.playids[content[1]][content[0]]))))
            data = self.manager.get(QNetworkRequest(QUrl(self.pictures[content[1]])))
            self.manager.finished.connect(lambda: self.load(data))
            self.current_list.setCurrentRow(self.current_list.currentRow()-1)
            self.player.play()
        except AttributeError:
            self.player.play()

    #      本地音乐查找start.
    def looking_music(self):
        """本地音乐查找组件。"""
        p = QPixmap()
        p.load('icons/local.jpg')
        self.detail_pic.setPixmap(p.scaled(200, 200))
        self.detail_name.setText("本地音乐")
        self.detail_author.setText("You, You, You")
        self.detail_tag.setText("Your Collection Music")
        self.hide_index()
        self.select_path.show()
        self.set_tables()
        self.locale_show_on_table(os.getcwd() + r"\myMusic")

    def set_path(self):
        file_path = QFileDialog.getExistingDirectory(self, 'Select Folder')
        self.locale_show_on_table(file_path)

    def locale_show_on_table(self, path):
        songs_list = [i for i in os.listdir(path) if i[-3:] == 'mp3']
        print(songs_list)
        self.table.setRowCount(len(songs_list))
        for i in range(len(songs_list)):
            temp = songs_list[i][:-4]
            temp2 = temp.split(' - ')
            self.table.setItem(i, 0, QTableWidgetItem(str(i)))
            self.table.setItem(i, 1, QTableWidgetItem(QIcon('icons/playlist.png'), ''))
            try:
                self.table.setItem(i, 2, QTableWidgetItem(temp2[1]))
                self.table.setItem(i, 3, QTableWidgetItem(temp2[0]))
            except IndexError:
                self.table.setItem(i, 2, QTableWidgetItem(temp))
                self.table.setItem(i, 3, QTableWidgetItem("暂时无法获取"))
                self.table.setItem(i, 4, QTableWidgetItem("暂时无法获取"))
                self.table.setItem(i, 5, QTableWidgetItem("暂时无法获取"))
                self.playids[temp] = {}
                self.playids[temp]["暂时无法获取"] = path + '\\' + songs_list[i]
                continue
            self.table.setItem(i, 4, QTableWidgetItem("暂时无法获取"))
            self.table.setItem(i, 5, QTableWidgetItem("暂时无法获取"))

            self.playids[temp2[1]] = {}
            self.playids[temp2[1]][temp2[0]] = path + '\\' + songs_list[i]
    #     本地音乐查找end.
    #    歌曲组件end.

    #    歌曲图片,时间和滚动条的设置。
    def load(self, data):
        """用于加载选中歌曲的图片。"""
        data = data.readAll()
        p = QPixmap()
        if data:
            p.loadFromData(data)
            self.song_pic.setPixmap(p.scaled(64, 64))
        else:
            p.load('icons/nosong.png')
            self.song_pic.setPixmap(p.scaled(64, 64))

    def set_time(self):
        """
            设置当前时间。
        """
        times = self.player.position() / 1000
        minutes = times // 60
        seconds = times % 60
        time = QTime(0, minutes, seconds)
        self.time1.setText(time.toString("mm:ss"))
        try:
            alltime = float(self.current_list.item(\
                self.current_list.currentRow()).text().split(' - ')[2].replace(':', '.'))
        except (AttributeError, ValueError):
            return
        curtime = float(time.toString('mm.ss'))
        self.slider.setValue((curtime / alltime) * 100)

    def slider_media(self):
        """
            拖动滚动条时时间的改变。基于时间的变化,若无法获取到时间是不变的,且会报ValueError的错误。当然可以随便写个2:00冒充。- -。
        """
        try:
            self.player.positionChanged.disconnect()
        except TypeError:
            pass
        content = self.current_list.item(self.current_list.currentRow()).text().split(' - ')
        alltime = float(content[2].replace(':', '.'))
        trans_alltime = int(alltime) * 60 + (alltime - int(alltime)) * 100
        currentTime = trans_alltime * self.slider.value()
        minuties = currentTime / 100 // 60
        seconds = currentTime / 100 % 60
        time = QTime(0, minuties, seconds)
        self.time1.setText(time.toString("mm:ss"))

    def slider_setdone(self):
        """
            鼠标放开后播放位置。待改进。
        """
        self.player.positionChanged.connect(self.set_time)
        content = self.current_list.item(self.current_list.currentRow()).text().split(' - ')
        alltime = float(content[2].replace(':', '.'))
        trans_alltime = int(alltime) * 60 + (alltime - int(alltime)) * 100
        currentTime = trans_alltime * self.slider.value()
        self.player.setPosition(currentTime * 10)

    #    设置歌曲播放模式。
    def set_modles(self):
        """
            切换图标及将循环标志变false。
        """
        if self.loop_flags:
            self.cycle.hide()
            self.single.show()
            self.loop_flags = False
        else:
            self.single.hide()
            self.cycle.show()
            self.loop_flags = True

    def loop(self):
        """
            设置为循环播放。默认。
        """
        if self.player.position() > 0 and self.player.state() == 0 and self.loop_flags:
            try:
                self.manager.disconnect()
            except TypeError:
                pass
            self.manager.clearAccessCache()
            content = self.current_list.item(self.current_list.currentRow()+1).text().split(' - ')
            self.current_list.setCurrentRow(self.current_list.currentRow()+1)
            try:
                self.player.setMedia(\
                    QMediaContent(QUrl(self.function.details_search(self.playids[content[1]][content[0]]))))
                data = self.manager.get(QNetworkRequest(QUrl(self.pictures[content[1]])))
                self.manager.finished.connect(lambda: self.load(data))
            except KeyError:
                self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.playids[content[1]][content[0]])))

            self.play_song()
        elif self.player.state() == 0:
            self.solo()

    def solo(self):
        """
            设置为单曲。
        """
        self.player.setPosition(0)
        self.play_song()
    # 歌曲部分end.
    # -------
    # 切换页面start。

    def songs_lists(self):
        """
            歌曲列表。
        """
        if self.current_list.flag:
            self.current_list.show()
            self.current_list.flag = False
        else:
            self.current_list.hide()
            self.current_list.flag = True

    def hide_index(self):
        """
            隐藏主页, 显示歌单详细信息。
        """
        self.centerLayout.setStretch(0, 160)
        self.centerLayout.setStretch(1, 1)
        self.centerLayout.setStretch(2, 850)
        self.centerLayout.setStretch(3, 0)
        self.centerLayout.setStretch(4, 0)
        self.index.hide()
        self.select_path.hide()
        self.current_list.hide()
        self.detail_pic.show()
        self.detail_name.show()
        self.detail_author.show()
        self.add_all_song.show()
        self.detail_tag.show()
        self.detail_description.show()
        self.table.show()

    def show_index(self):
        """
            显示主页。
        """
        self.centerLayout.setStretch(0, 160)
        self.centerLayout.setStretch(1, 1)
        self.centerLayout.setStretch(2, 0)
        self.centerLayout.setStretch(3, 850)
        self.centerLayout.setStretch(4, 0)
        self.current_list.hide()
        self.detail_pic.hide()
        self.detail_name.hide()
        self.select_path.hide()
        self.detail_author.hide()
        self.add_all_song.hide()
        self.detail_tag.hide()
        self.detail_description.hide()
        self.table.hide()
        self.index.show()
    # 切换页面end.

    # 设置布局。
    def set_layouts(self):
        """
            布局。
        """
        # 头布局start.
        self.topLayout.setObjectName('Headerhbox')
        self.topLayout.addWidget(self.header_icon)
        self.topLayout.addWidget(self.header_text)
        self.topLayout.addWidget(self.spacing2)
        self.topLayout.addWidget(self.search_line)
        self.topLayout.addWidget(self.btn_search)
        self.topLayout.addStretch(1)
        self.topLayout.addWidget(self.lbe_pic)
        self.topLayout.addWidget(self.btn_login)
        self.topLayout.addWidget(self.spacing)
        self.topLayout.addWidget(self.btn_min)
        self.topLayout.addWidget(self.btn_max)
        self.topLayout.addWidget(self.btn_exit)
        self.topLayout.setSpacing(7)
        # -------
        self.mainLayout.addLayout(self.topLayout, 0, 0, Qt.AlignTop)
        self.mainLayout.addWidget(self.header_hr, 1, 0, Qt.AlignTop)
        # 头布局end.
        # --------
        # 中心布局start.
        #  左部分start.
        self.leftLayout.addWidget(self.find_music)
        self.leftLayout.addWidget(self.locale_music)
        self.leftLayout.addWidget(self.songs_list)
        self.leftLayout.addWidget(self.playlist)
        self.leftLayout.setSpacing(10)
        #  左部分end。
        # -------
        #  右部分start.
        self.rightLayout.addLayout(self.rightLayout1)
        self.rightLayout1.addWidget(self.detail_pic)
        self.rightLayout1.addLayout(self.rightLayout2)
        self.rightLayout1.setStretch(0, 1)
        self.rightLayout1.setStretch(1, 5)
        self.rightLayout21.addWidget(self.detail_name)
        self.rightLayout21.addWidget(self.select_path)
        self.rightLayout21.addStretch(1)
        self.rightLayout2.addLayout(self.rightLayout21)
        self.rightLayout2.addWidget(self.detail_author)
        self.playLayout.addWidget(self.add_all_song)
        self.playLayout.addStretch(1)
        self.rightLayout2.addLayout(self.playLayout)
        self.rightLayout2.addWidget(self.detail_tag)
        self.rightLayout2.addWidget(self.detail_description)
        self.rightLayout.addWidget(self.table)
        self.rightLayout.setStretch(0, 1)
        self.rightLayout.setStretch(1, 2)
        #  右部分end.
        # -------
        self.centerLayout.addLayout(self.leftLayout)
        self.centerLayout.addWidget(self.spacing3)
        self.centerLayout.addLayout(self.rightLayout)
        self.centerLayout.addWidget(self.index)
        self.centerLayout.addWidget(self.current_list)
        self.centerLayout.setStretch(0, 180)
        self.centerLayout.setStretch(1, 1)
        self.centerLayout.setStretch(2, 0)
        self.centerLayout.setStretch(3, 830)
        self.centerLayout.setStretch(4, 0)
        self.mainLayout.addLayout(self.centerLayout, 2, 0, Qt.AlignTop | Qt.AlignLeft)
        # 中心布局end.
        # -------
        # 下部分start.
        self.bottomLayout.addWidget(self.stop)
        self.bottomLayout.addWidget(self.beforeSong)
        self.bottomLayout.addWidget(self.play)
        self.bottomLayout.addWidget(self.pause)
        self.bottomLayout.addWidget(self.nextSong)
        self.bottomLayout.addWidget(self.song_pic)
        self.bottomLayout.addWidget(self.time1)
        self.bottomLayout1.addWidget(self.song_name)
        self.bottomLayout1.addWidget(self.slider)
        self.bottomLayout.addLayout(self.bottomLayout1)
        self.bottomLayout.addWidget(self.time2)
        self.bottomLayout.addWidget(self.cycle)
        self.bottomLayout.addWidget(self.single)
        self.bottomLayout.addWidget(self.btn_list)
        self.bottomLayout.setStretch(6, 1)
        self.bottomLayout.setStretch(7, 6)
        self.bottomLayout.setStretch(8, 1)
        self.mainLayout.addWidget(self.spacing4, 3, 0, Qt.AlignTop)
        self.mainLayout.addLayout(self.bottomLayout, 3, 0, Qt.AlignBottom)
        # self.mainLayout.addWidget(self.current_list, 2, 0, Qt.AlignBottom | Qt.AlignRight)
        # 下部分end.
        self.mainLayout.setRowStretch(1, 1)
        self.mainLayout.setRowStretch(2, 20)
        self.mainLayout.setRowStretch(3, 3)
        return self.mainLayout

    """重写鼠标事件,实现窗口拖动。"""
    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos()-self.pos()
            event.accept()

    def mouseMoveEvent(self, event):
        try:
            if event.buttons() and Qt.LeftButton:
                self.move(event.globalPos()-self.m_DragPosition)
                event.accept()
        except AttributeError:
            pass

    def mouseReleaseEvent(self, event):
        self.m_drag = False

    """按键绑定。。"""
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Enter-1:
            self.song_search()

    """退出窗口时做的一些事。"""
    def closeEvent(self, event):
        # 退出时保存歌曲列表缓存。
        try:
            with open('data/music/load/playids.pkl', 'wb') as f:
                pickle.dump(self.playids, f)
        except FileNotFoundError:
            pass

    """界面开始前的一些事。"""
    def showEvent(self, event):
        # 查看是否有歌曲缓存。
        try:
            with open('data/music/load/playids.pkl', 'rb') as r:
                self.playids = pickle.load(r)
        # 没有就算了。
        except FileNotFoundError:
            pass
        # 没有也不会报错。
        for i in os.listdir('.' + '/data/music/'):
            if os.path.isfile('.' + '/data/music/' + i):
                self.current_list.addItem(i.replace('.', ':'))
                with open('.' + '/data/music/' + i, 'r') as f:
                    self.pictures[i.split(' - ')[1]] = f.read()
        # 有的话设置为0,防止其他功能报错。
        self.current_list.setCurrentRow(0)