Upd horsy to 140320221219

This commit is contained in:
BarsTiger
2022-03-14 12:46:48 +02:00
parent c85b2be089
commit 988832acfb
25 changed files with 1458 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
from PyQt5 import QtCore, QtWidgets
class Ui_DelSongs(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(300, 510)
MainWindow.setMinimumSize(QtCore.QSize(300, 510))
MainWindow.setMaximumSize(QtCore.QSize(300, 510))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(0, 0, 300, 461))
self.listWidget.setObjectName("listWidget")
self.delButton = QtWidgets.QPushButton(self.centralwidget)
self.delButton.setGeometry(QtCore.QRect(0, 460, 300, 23))
self.delButton.setObjectName("delButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 300, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Songs manager"))
self.delButton.setText(_translate("MainWindow", "Delete selected song"))

View File

@@ -0,0 +1,36 @@
from PyQt5 import QtCore, QtWidgets
class Ui_ExtendedMenu(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(151, 74)
MainWindow.setMinimumSize(QtCore.QSize(151, 74))
MainWindow.setMaximumSize(QtCore.QSize(151, 74))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.prosearchButton = QtWidgets.QPushButton(self.centralwidget)
self.prosearchButton.setGeometry(QtCore.QRect(0, 0, 150, 50))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prosearchButton.sizePolicy().hasHeightForWidth())
self.prosearchButton.setSizePolicy(sizePolicy)
self.prosearchButton.setMaximumSize(QtCore.QSize(150, 50))
self.prosearchButton.setObjectName("prosearchButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 151, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Extended functions"))
self.prosearchButton.setText(_translate("MainWindow", "Pro search"))

View File

@@ -0,0 +1,42 @@
from PyQt5 import QtCore, QtWidgets
import os
class Ui_MainBuild(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(161, 157)
MainWindow.setMinimumSize(QtCore.QSize(161, 157))
MainWindow.setMaximumSize(QtCore.QSize(161, 157))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(0, 0, 161, 111))
self.listWidget.setObjectName("listWidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(0, 110, 161, 23))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 161, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
for file in os.listdir(os.getcwd()):
if file == "MultiMate_Player.py":
self.listWidget.addItem(file)
elif file == "MultiMate_Player.pyw":
self.listWidget.addItem(file)
elif file == "MultiMate_Player.exe":
self.listWidget.addItem(file)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Choose main build"))
self.pushButton.setText(_translate("MainWindow", "Choose main build"))

View File

@@ -0,0 +1,215 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import platform
import os
class Ui_MainWindow(QtWidgets.QMainWindow):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(801, 580)
MainWindow.setMinimumSize(QtCore.QSize(801, 580))
MainWindow.setMaximumSize(QtCore.QSize(801, 580))
MainWindow.setWindowIcon(QtGui.QIcon('resources/img/MultiMate.ico'))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.timeline = QtWidgets.QSlider(self.centralwidget)
self.timeline.setGeometry(QtCore.QRect(10, 490, 781, 22))
self.timeline.setPageStep(1)
self.timeline.setOrientation(QtCore.Qt.Horizontal)
self.timeline.setObjectName("timeline")
self.timeline.setMaximum(1000)
self.playpausebutton = QtWidgets.QPushButton(self.centralwidget)
self.playpausebutton.setEnabled(True)
self.playpausebutton.setGeometry(QtCore.QRect(390, 520, 40, 40))
font = QtGui.QFont()
font.setKerning(True)
self.playpausebutton.setFont(font)
self.playpausebutton.setStyleSheet("background-color: rgba(10, 0, 0, 0);\n"
"")
self.playpausebutton.setText("")
self.playpausebutton.setObjectName("playpausebutton")
self.playpausePicture = QtWidgets.QLabel(self.centralwidget)
self.playpausePicture.setGeometry(QtCore.QRect(390, 520, 40, 40))
self.playpausePicture.setText("")
self.playpausePicture.setPixmap(QtGui.QPixmap("resources/img/MultiMate40x40.png"))
self.playpausePicture.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.playpausePicture.setObjectName("playpausePicture")
self.prevbutton = QtWidgets.QPushButton(self.centralwidget)
self.prevbutton.setEnabled(True)
self.prevbutton.setGeometry(QtCore.QRect(340, 520, 40, 40))
font = QtGui.QFont()
font.setKerning(True)
self.prevbutton.setFont(font)
self.prevbutton.setStyleSheet("background-color: rgba(10, 0, 0, 0);\n"
"")
self.prevbutton.setText("")
self.prevbutton.setObjectName("prevbutton")
self.prevPicture = QtWidgets.QLabel(self.centralwidget)
self.prevPicture.setGeometry(QtCore.QRect(340, 520, 40, 40))
self.prevPicture.setText("")
self.prevPicture.setPixmap(QtGui.QPixmap("resources/img/prev.png"))
self.prevPicture.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.prevPicture.setObjectName("prevPicture")
self.nextbutton = QtWidgets.QPushButton(self.centralwidget)
self.nextbutton.setEnabled(True)
self.nextbutton.setGeometry(QtCore.QRect(440, 520, 40, 40))
font = QtGui.QFont()
font.setKerning(True)
self.nextbutton.setFont(font)
self.nextbutton.setStyleSheet("background-color: rgba(10, 0, 0, 0);\n"
"")
self.nextbutton.setText("")
self.nextbutton.setObjectName("nextbutton")
self.nextPicture = QtWidgets.QLabel(self.centralwidget)
self.nextPicture.setGeometry(QtCore.QRect(440, 520, 40, 40))
self.nextPicture.setText("")
self.nextPicture.setPixmap(QtGui.QPixmap("resources/img/next.png"))
self.nextPicture.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.nextPicture.setObjectName("nextPicture")
self.speedBox = QtWidgets.QDoubleSpinBox(self.centralwidget)
self.speedBox.setGeometry(QtCore.QRect(10, 515, 62, 22))
self.speedBox.setDecimals(1)
self.speedBox.setProperty("value", 1.0)
self.speedBox.setSingleStep(0.2)
self.speedBox.setObjectName("speedBox")
self.timenow = QtWidgets.QTextEdit(self.centralwidget)
self.timenow.setGeometry(QtCore.QRect(713, 515, 81, 23))
self.timenow.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.timenow.setObjectName("timenow")
self.speedTextLabel = QtWidgets.QLabel(self.centralwidget)
self.speedTextLabel.setGeometry(QtCore.QRect(25, 536, 47, 13))
self.speedTextLabel.setObjectName("speedTextLabel")
self.timeTextLabel = QtWidgets.QLabel(self.centralwidget)
self.timeTextLabel.setGeometry(QtCore.QRect(740, 536, 47, 13))
self.timeTextLabel.setObjectName("timeTextLabel")
self.volumeDial = QtWidgets.QDial(self.centralwidget)
self.volumeDial.setGeometry(QtCore.QRect(719, 0, 81, 81))
self.volumeDial.setStyleSheet("")
self.volumeDial.setMinimum(1)
self.volumeDial.setMaximum(100)
self.volumeDial.setPageStep(1)
self.volumeDial.setProperty("value", 100)
self.volumeDial.setObjectName("volumeDial")
self.VolDialBG = QtWidgets.QLabel(self.centralwidget)
self.VolDialBG.setGeometry(QtCore.QRect(720, 0, 81, 81))
self.VolDialBG.setText("")
self.VolDialBG.setPixmap(QtGui.QPixmap("resources/img/MultiMate80x80.png"))
self.VolDialBG.setObjectName("VolDialBG")
self.playlistsComboBox = QtWidgets.QComboBox(self.centralwidget)
self.playlistsComboBox.setGeometry(QtCore.QRect(0, 0, 231, 22))
self.playlistsComboBox.setCurrentText("")
self.playlistsComboBox.setDuplicatesEnabled(True)
self.playlistsComboBox.setObjectName("playlistsComboBox")
for playlist in os.listdir(os.getcwd()):
self.playlistsComboBox.addItem(playlist)
self.nowPlaying = QtWidgets.QTextBrowser(self.centralwidget)
self.nowPlaying.setGeometry(QtCore.QRect(10, 460, 781, 23))
self.nowPlaying.setObjectName("nowPlaying")
self.openPlaylistButton = QtWidgets.QPushButton(self.centralwidget)
self.openPlaylistButton.setGeometry(QtCore.QRect(230, 0, 75, 23))
self.openPlaylistButton.setObjectName("openPlaylistButton")
self.songList = QtWidgets.QListWidget(self.centralwidget)
self.songList.setGeometry(QtCore.QRect(0, 43, 301, 411))
self.songList.setObjectName("songList")
self.TextAllSongs = QtWidgets.QTextEdit(self.centralwidget)
self.TextAllSongs.setGeometry(QtCore.QRect(0, 20, 301, 23))
self.TextAllSongs.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.TextAllSongs.setObjectName("TextAllSongs")
self.toFindName = QtWidgets.QTextEdit(self.centralwidget)
self.toFindName.setGeometry(QtCore.QRect(310, 0, 331, 23))
self.toFindName.setObjectName("toFindName")
self.findSongButton = QtWidgets.QPushButton(self.centralwidget)
self.findSongButton.setGeometry(QtCore.QRect(640, 0, 75, 23))
self.findSongButton.setObjectName("findSongButton")
self.foundSongs = QtWidgets.QComboBox(self.centralwidget)
self.foundSongs.setGeometry(QtCore.QRect(310, 30, 331, 22))
self.foundSongs.setObjectName("foundSongs")
self.addThisSongButton = QtWidgets.QPushButton(self.centralwidget)
self.addThisSongButton.setGeometry(QtCore.QRect(640, 30, 75, 23))
self.addThisSongButton.setObjectName("addThisSongButton")
self.mixButton = QtWidgets.QPushButton(self.centralwidget)
self.mixButton.setGeometry(QtCore.QRect(720, 90, 75, 41))
self.mixButton.setObjectName("mixButton")
self.playlistSettingsButton = QtWidgets.QPushButton(self.centralwidget)
self.playlistSettingsButton.setGeometry(QtCore.QRect(720, 140, 75, 51))
self.playlistSettingsButton.setObjectName("playlistSettingsButton")
self.settingsButton = QtWidgets.QPushButton(self.centralwidget)
self.settingsButton.setGeometry(QtCore.QRect(720, 200, 75, 45))
self.settingsButton.setObjectName("settingsButton")
self.extendedFunctButton = QtWidgets.QPushButton(self.centralwidget)
self.extendedFunctButton.setGeometry(QtCore.QRect(720, 260, 75, 45))
self.extendedFunctButton.setObjectName("extendedFunctButton")
if platform.system() == "Darwin": # for MacOS
self.videoframe = QtWidgets.QMacCocoaViewContainer(self.centralwidget)
else:
self.videoframe = QtWidgets.QFrame(self.centralwidget)
self.videoframe.setGeometry(QtCore.QRect(310, 60, 394, 394))
self.videoframe.setObjectName("videoframe")
self.timeline.raise_()
self.playpausePicture.raise_()
self.prevPicture.raise_()
self.nextPicture.raise_()
self.speedBox.raise_()
self.nextbutton.raise_()
self.prevbutton.raise_()
self.playpausebutton.raise_()
self.timenow.raise_()
self.speedTextLabel.raise_()
self.timeTextLabel.raise_()
self.VolDialBG.raise_()
self.volumeDial.raise_()
self.playlistsComboBox.raise_()
self.nowPlaying.raise_()
self.openPlaylistButton.raise_()
self.songList.raise_()
self.TextAllSongs.raise_()
self.toFindName.raise_()
self.findSongButton.raise_()
self.foundSongs.raise_()
self.addThisSongButton.raise_()
self.mixButton.raise_()
self.playlistSettingsButton.raise_()
self.videoframe.raise_()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 801, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.timer = QtCore.QTimer(self)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MultiMate Player"))
self.speedBox.setPrefix(_translate("MainWindow", "x"))
self.speedTextLabel.setText(_translate("MainWindow", "Speed"))
self.timeTextLabel.setText(_translate("MainWindow", "Time"))
self.nowPlaying.setPlaceholderText(_translate("MainWindow", "Choose playlist and open it..."))
self.openPlaylistButton.setText(_translate("MainWindow", "Open playlist"))
self.TextAllSongs.setHtml(_translate("MainWindow",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Songs in playlist</p></body></html>"))
self.findSongButton.setText(_translate("MainWindow", "Find song"))
self.addThisSongButton.setText(_translate("MainWindow", "Add this song"))
self.mixButton.setText(_translate("MainWindow", "Mix"))
self.playlistSettingsButton.setText(_translate("MainWindow", "Playlist \nsettings"))
self.settingsButton.setText(_translate("MainWindow", "Settings"))
self.extendedFunctButton.setText(_translate("MainWindow", "Extended \n functions"))

View File

@@ -0,0 +1,36 @@
from PyQt5 import QtCore, QtWidgets
class Ui_PlaylistSettings(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(160, 97)
MainWindow.setMinimumSize(QtCore.QSize(160, 97))
MainWindow.setMaximumSize(QtCore.QSize(160, 97))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 160, 80))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.deletesongButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.deletesongButton.setObjectName("deletesongButton")
self.verticalLayout.addWidget(self.deletesongButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 160, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Playlist settings"))
self.deletesongButton.setText(_translate("MainWindow", "Manage songs in playlist"))

View File

@@ -0,0 +1,49 @@
from PyQt5 import QtCore, QtWidgets
class Ui_ProSearch(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(750, 600)
MainWindow.setMinimumSize(QtCore.QSize(750, 600))
MainWindow.setMaximumSize(QtCore.QSize(750, 600))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(0, 180, 750, 361))
self.listWidget.setObjectName("listWidget")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(160, 70, 440, 30))
self.lineEdit.setStyleSheet("border-radius:\n"
" 1 px;")
self.lineEdit.setReadOnly(False)
self.lineEdit.setObjectName("lineEdit")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(285, 20, 180, 31))
self.label.setObjectName("label")
self.searchButton = QtWidgets.QPushButton(self.centralwidget)
self.searchButton.setGeometry(QtCore.QRect(300, 110, 150, 30))
self.searchButton.setObjectName("searchButton")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(300, 550, 150, 31))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 750, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Pro search"))
self.lineEdit.setPlaceholderText(_translate("MainWindow", "Never gonna give you up"))
self.label.setText(_translate("MainWindow",
"<html><head/><body><p><span style=\" font-size:18pt;\">Advanced search</span></p></body></html>"))
self.searchButton.setText(_translate("MainWindow", "Search"))
self.pushButton.setText(_translate("MainWindow", "Add selected"))

View File

@@ -0,0 +1,39 @@
from PyQt5 import QtCore, QtWidgets
from resources.lib.config import config
class Ui_RPCsettings(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(160, 100)
MainWindow.setMinimumSize(QtCore.QSize(160, 100))
MainWindow.setMaximumSize(QtCore.QSize(160, 100))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(9, 0, 151, 80))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.ShowRPCcheckBox = QtWidgets.QCheckBox(self.verticalLayoutWidget)
self.ShowRPCcheckBox.setObjectName("ShowRPCcheckBox")
self.verticalLayout.addWidget(self.ShowRPCcheckBox)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 160, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.ShowRPCcheckBox.setChecked(config['showrpc'])
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "RPC settings"))
self.ShowRPCcheckBox.setText(_translate("MainWindow", "Show RPC"))

View File

@@ -0,0 +1,48 @@
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Settings(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(160, 100)
MainWindow.setMinimumSize(QtCore.QSize(160, 100))
MainWindow.setMaximumSize(QtCore.QSize(160, 100))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 160, 80))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.updateButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.updateButton.setObjectName("updateButton")
self.verticalLayout.addWidget(self.updateButton)
self.appBuildButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.appBuildButton.setObjectName("appBuildButton")
self.verticalLayout.addWidget(self.appBuildButton)
self.RPCButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.RPCButton.setObjectName("RPCButton")
self.verticalLayout.addWidget(self.RPCButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 160, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Settings"))
self.updateButton.setText(_translate("MainWindow", "Upgrade player"))
self.appBuildButton.setText(_translate("MainWindow", "Choose main build"))
self.RPCButton.setText(_translate("MainWindow", "Discord RPC settings"))

View File

@@ -0,0 +1,37 @@
from PyQt5 import QtCore, QtWidgets
class Ui_Updater(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(160, 97)
MainWindow.setMinimumSize(QtCore.QSize(160, 97))
MainWindow.setMaximumSize(QtCore.QSize(160, 97))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 160, 80))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.updateButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.updateButton.setObjectName("updateButton")
self.verticalLayout.addWidget(self.updateButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 160, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Updater"))
self.updateButton.setText(_translate("MainWindow", "Download newest"))

View File

@@ -0,0 +1,57 @@
import sys
from PyQt5 import QtWidgets
from resources.gui.Ui_DelSongs import Ui_DelSongs
from resources.gui.Ui_ExtendedMenu import Ui_ExtendedMenu
from resources.gui.Ui_MainBuild import Ui_MainBuild
from resources.gui.Ui_MainWindow import Ui_MainWindow
from resources.gui.Ui_PlaylistSettings import Ui_PlaylistSettings
from resources.gui.Ui_ProSearch import Ui_ProSearch
from resources.gui.Ui_RPCsettings import Ui_RPCsettings
from resources.gui.Ui_Settings import Ui_Settings
from resources.gui.Ui_Updater import Ui_Updater
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
appPlSet = QtWidgets.QApplication(sys.argv)
MainWindowPlSet = QtWidgets.QMainWindow()
uiPlSet = Ui_PlaylistSettings()
uiPlSet.setupUi(MainWindowPlSet)
appDelS = QtWidgets.QApplication(sys.argv)
MainWindowDelS = QtWidgets.QMainWindow()
uiDelS = Ui_DelSongs()
uiDelS.setupUi(MainWindowDelS)
appSet = QtWidgets.QApplication(sys.argv)
MainWindowSet = QtWidgets.QMainWindow()
uiSet = Ui_Settings()
uiSet.setupUi(MainWindowSet)
appUpd = QtWidgets.QApplication(sys.argv)
MainWindowUpd = QtWidgets.QMainWindow()
uiUpd = Ui_Updater()
uiUpd.setupUi(MainWindowUpd)
appExt = QtWidgets.QApplication(sys.argv)
MainWindowExt = QtWidgets.QMainWindow()
uiExt = Ui_ExtendedMenu()
uiExt.setupUi(MainWindowExt)
appPSearch = QtWidgets.QApplication(sys.argv)
MainWindowPSearch = QtWidgets.QMainWindow()
uiPSearch = Ui_ProSearch()
uiPSearch.setupUi(MainWindowPSearch)
appRPCSet = QtWidgets.QApplication(sys.argv)
MainWindowRPCSet = QtWidgets.QMainWindow()
uiRPCSet = Ui_RPCsettings()
uiRPCSet.setupUi(MainWindowRPCSet)
appMainBuild = QtWidgets.QApplication(sys.argv)
MainWindowMainBuild = QtWidgets.QMainWindow()
uiMainBuild = Ui_MainBuild()
uiMainBuild.setupUi(MainWindowMainBuild)

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,32 @@
import os
import json
configfile = "resources/cfg.cfg"
if not os.path.isfile(configfile):
cfgwrite = open(configfile, 'w+')
empty = {}
json.dump(empty, cfgwrite, indent=3)
cfgwrite.close()
with open(configfile) as cfgread:
config = json.load(cfgread)
try:
config['mainbuild']
except:
if "MultiMate_Player.py" in os.listdir(os.getcwd()):
config['mainbuild'] = 'MultiMate_Player.py'
elif "MultiMate_Player.pyw" in os.listdir(os.getcwd()):
config['mainbuild'] = 'MultiMate_Player.pyw'
elif "MultiMate_Player.exe" in os.listdir(os.getcwd()):
config['mainbuild'] = 'MultiMate_Player.exe'
with open(configfile, 'w+') as cfgwrite:
json.dump(config, cfgwrite, indent=3)
try:
config['showrpc']
except:
config['showrpc'] = True
with open(configfile, 'w+') as cfgwrite:
json.dump(config, cfgwrite, indent=3)

View File

@@ -0,0 +1,5 @@
import os
def cls():
os.system('cls' if os.name == 'nt' else 'clear')

View File

@@ -0,0 +1,13 @@
from pypresence import Presence
from resources.lib.config import config
import time
rpc = Presence("896669007342633000")
try:
rpc.connect()
if config['showrpc']:
rpc.update(details="Just started app", state="Nothing is beeing listened...", large_image="multimate",
start=int(time.time()))
except:
pass

View File

@@ -0,0 +1,65 @@
import json
import requests
import urllib.parse
class YoutubeSearch:
def __init__(self, search_terms: str, max_results=None):
self.search_terms = search_terms
self.max_results = max_results
self.videos = self._search()
def _search(self):
encoded_search = urllib.parse.quote_plus(self.search_terms)
BASE_URL = "https://youtube.com"
url = f"{BASE_URL}/search?q={encoded_search}"
response = requests.get(url).text
while "ytInitialData" not in response:
response = requests.get(url).text
results = self._parse_html(response)
if self.max_results is not None and len(results) > self.max_results:
return results[: self.max_results]
return results
def _parse_html(self, response):
results = []
start = (
response.index("ytInitialData")
+ len("ytInitialData")
+ 3
)
end = response.index("};", start) + 1
json_str = response[start:end]
data = json.loads(json_str)
videos = data["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"][
"sectionListRenderer"
]["contents"][0]["itemSectionRenderer"]["contents"]
for video in videos:
res = {}
if "videoRenderer" in video.keys():
video_data = video.get("videoRenderer", {})
res["id"] = video_data.get("videoId", None)
res["thumbnails"] = [thumb.get("url", None) for thumb in video_data.get("thumbnail", {}).get("thumbnails", [{}]) ]
res["title"] = video_data.get("title", {}).get("runs", [[{}]])[0].get("text", None)
res["long_desc"] = video_data.get("descriptionSnippet", {}).get("runs", [{}])[0].get("text", None)
res["channel"] = video_data.get("longBylineText", {}).get("runs", [[{}]])[0].get("text", None)
res["duration"] = video_data.get("lengthText", {}).get("simpleText", 0)
res["views"] = video_data.get("viewCountText", {}).get("simpleText", 0)
res["publish_time"] = video_data.get("publishedTimeText", {}).get("simpleText", 0)
res["url_suffix"] = video_data.get("navigationEndpoint", {}).get("commandMetadata", {}).get("webCommandMetadata", {}).get("url", None)
results.append(res)
return results
def to_dict(self, clear_cache=True):
result = self.videos
if clear_cache:
self.videos = ""
return result
def to_json(self, clear_cache=True):
result = json.dumps({"videos": self.videos})
if clear_cache:
self.videos = ""
return result

View File

@@ -0,0 +1,558 @@
import os
import re
import sys
import time
import logging
import subprocess
if sys.version_info[:2] >= (3, 0):
# pylint: disable=E0611,F0401,I0011
from urllib.request import urlopen, build_opener
from urllib.error import HTTPError, URLError
from urllib.parse import parse_qs, urlparse
uni, pyver = str, 3
else:
from urllib2 import urlopen, build_opener, HTTPError, URLError
from urlparse import parse_qs, urlparse
uni, pyver = unicode, 2
early_py_version = sys.version_info[:2] < (2, 7)
dbg = logging.debug
def extract_video_id(url):
""" Extract the video id from a url, return video id as str. """
idregx = re.compile(r'[\w-]{11}$')
url = str(url).strip()
if idregx.match(url):
return url # ID of video
if '://' not in url:
url = '//' + url
parsedurl = urlparse(url)
if parsedurl.netloc in ('youtube.com', 'www.youtube.com', 'm.youtube.com', 'gaming.youtube.com'):
query = parse_qs(parsedurl.query)
if 'v' in query and idregx.match(query['v'][0]):
return query['v'][0]
elif parsedurl.netloc in ('youtu.be', 'www.youtu.be'):
vidid = parsedurl.path.split('/')[-1] if parsedurl.path else ''
if idregx.match(vidid):
return vidid
err = "Need 11 character video id or the URL of the video. Got %s"
raise ValueError(err % url)
class BasePafy(object):
""" Class to represent a YouTube video. """
def __init__(self, video_url, basic=True, gdata=False,
size=False, callback=None, ydl_opts=None):
""" Set initial values. """
self.version = 1
self.videoid = extract_video_id(video_url)
self.watchv_url = "http://www.youtube.com/watch?v=%s" % self.videoid
self.callback = callback
self._have_basic = False
self._have_gdata = False
self._description = None
self._likes = None
self._dislikes = None
self._category = None
self._published = None
self._username = None
self._streams = []
self._oggstreams = []
self._m4astreams = []
self._allstreams = []
self._videostreams = []
self._audiostreams = []
self._title = None
self._rating = None
self._length = None
self._author = None
self._duration = None
self._keywords = None
self._bigthumb = None
self._viewcount = None
self._bigthumbhd = None
self._bestthumb = None
self._mix_pl = None
self.expiry = None
if basic:
self._fetch_basic()
if gdata:
self._fetch_gdata()
if size:
for s in self.allstreams:
# pylint: disable=W0104
s.get_filesize()
def _fetch_basic(self):
""" Fetch basic data and streams. """
raise NotImplementedError
def _fetch_gdata(self):
""" Extract gdata values, fetch gdata if necessary. """
raise NotImplementedError
def _process_streams(self):
""" Create Stream object lists from internal stream maps. """
raise NotImplementedError
def __repr__(self):
""" Print video metadata. Return utf8 string. """
if self._have_basic:
info = [("Title", self.title),
("Author", self.author),
("ID", self.videoid),
("Duration", self.duration),
("Rating", self.rating),
("Views", self.viewcount)]
nfo = "\n".join(["%s: %s" % i for i in info])
else:
nfo = "Pafy object: %s [%s]" % (self.videoid,
self.title[:45] + "..")
return nfo.encode("utf8", "replace") if pyver == 2 else nfo
@property
def streams(self):
""" The streams for a video. Returns list."""
if not self._streams:
self._process_streams()
return self._streams
@property
def allstreams(self):
""" All stream types for a video. Returns list. """
if not self._allstreams:
self._process_streams()
return self._allstreams
@property
def audiostreams(self):
""" Return a list of audio Stream objects. """
if not self._audiostreams:
self._process_streams()
return self._audiostreams
@property
def videostreams(self):
""" The video streams for a video. Returns list. """
if not self._videostreams:
self._process_streams()
return self._videostreams
@property
def oggstreams(self):
""" Return a list of ogg encoded Stream objects. """
if not self._oggstreams:
self._process_streams()
return self._oggstreams
@property
def m4astreams(self):
""" Return a list of m4a encoded Stream objects. """
if not self._m4astreams:
self._process_streams()
return self._m4astreams
@property
def title(self):
""" Return YouTube video title as a string. """
if not self._title:
self._fetch_basic()
return self._title
@property
def author(self):
""" The uploader of the video. Returns str. """
if not self._author:
self._fetch_basic()
return self._author
@property
def rating(self):
""" Rating for a video. Returns float. """
if not self._rating:
self._fetch_basic()
return self._rating
@property
def length(self):
""" Length of a video in seconds. Returns int. """
if not self._length:
self._fetch_basic()
return self._length
@property
def viewcount(self):
""" Number of views for a video. Returns int. """
if not self._viewcount:
self._fetch_basic()
return self._viewcount
@property
def bigthumb(self):
""" Large thumbnail image url. Returns str. """
self._fetch_basic()
return self._bigthumb
@property
def bigthumbhd(self):
""" Extra large thumbnail image url. Returns str. """
self._fetch_basic()
return self._bigthumbhd
@property
def duration(self):
""" Duration of a video (HH:MM:SS). Returns str. """
if not self._length:
self._fetch_basic()
self._duration = time.strftime('%H:%M:%S', time.gmtime(self._length))
self._duration = uni(self._duration)
return self._duration
@property
def keywords(self):
""" Return keywords as list of str. """
if not self._keywords:
self._fetch_gdata()
return self._keywords
@property
def category(self):
""" YouTube category of the video. Returns string. """
if not self._category:
self._fetch_gdata()
return self._category
@property
def description(self):
""" Description of the video. Returns string. """
if not self._description:
self._fetch_gdata()
return self._description
@property
def username(self):
""" Return the username of the uploader. """
if not self._username:
self._fetch_basic()
return self._username
@property
def published(self):
""" The upload date and time of the video. Returns string. """
if not self._published:
self._fetch_gdata()
return self._published.replace(".000Z", "").replace("T", " ")
@property
def likes(self):
""" The number of likes for the video. Returns int. """
if not self._likes:
self._fetch_basic()
return self._likes
@property
def dislikes(self):
""" The number of dislikes for the video. Returns int. """
if not self._dislikes:
self._fetch_basic()
return self._dislikes
def _getbest(self, preftype="any", ftypestrict=True, vidonly=False):
"""
Return the highest resolution video available.
Select from video-only streams if vidonly is True
"""
streams = self.videostreams if vidonly else self.streams
if not streams:
return None
def _sortkey(x, key3d=0, keyres=0, keyftype=0):
""" sort function for max(). """
key3d = "3D" not in x.resolution
keyres = int(x.resolution.split("x")[0])
keyftype = preftype == x.extension
strict = (key3d, keyftype, keyres)
nonstrict = (key3d, keyres, keyftype)
return strict if ftypestrict else nonstrict
r = max(streams, key=_sortkey)
if ftypestrict and preftype != "any" and r.extension != preftype:
return None
else:
return r
def getbestvideo(self, preftype="any", ftypestrict=True):
"""
Return the best resolution video-only stream.
set ftypestrict to False to return a non-preferred format if that
has a higher resolution
"""
return self._getbest(preftype, ftypestrict, vidonly=True)
def getbest(self, preftype="any", ftypestrict=True):
"""
Return the highest resolution video+audio stream.
set ftypestrict to False to return a non-preferred format if that
has a higher resolution
"""
return self._getbest(preftype, ftypestrict, vidonly=False)
def getbestaudio(self, preftype="any", ftypestrict=True):
""" Return the highest bitrate audio Stream object."""
if not self.audiostreams:
return None
def _sortkey(x, keybitrate=0, keyftype=0):
""" Sort function for max(). """
keybitrate = int(x.rawbitrate)
keyftype = preftype == x.extension
strict, nonstrict = (keyftype, keybitrate), (keybitrate, keyftype)
return strict if ftypestrict else nonstrict
r = max(self.audiostreams, key=_sortkey)
if ftypestrict and preftype != "any" and r.extension != preftype:
return None
else:
return r
@classmethod
def _content_available(cls, url):
try:
response = urlopen(url)
except HTTPError:
return False
else:
return response.getcode() < 300
def getbestthumb(self):
""" Return the best available thumbnail."""
if not self._bestthumb:
part_url = "http://i.ytimg.com/vi/%s/" % self.videoid
# Thumbnail resolution sorted in descending order
thumbs = ("maxresdefault.jpg",
"sddefault.jpg",
"hqdefault.jpg",
"mqdefault.jpg",
"default.jpg")
for thumb in thumbs:
url = part_url + thumb
if self._content_available(url):
return url
return self._bestthumb
def populate_from_playlist(self, pl_data):
""" Populate Pafy object with items fetched from playlist data. """
self._title = pl_data.get("title")
self._author = pl_data.get("author")
self._length = int(pl_data.get("length_seconds", 0))
self._rating = pl_data.get("rating", 0.0)
self._viewcount = "".join(re.findall(r"\d", "{0}".format(pl_data.get("views", "0"))))
self._viewcount = int(self._viewcount)
self._description = pl_data.get("description")
class BaseStream(object):
""" YouTube video stream class. """
def __init__(self, parent):
""" Set initial values. """
self._itag = None
self._mediatype = None
self._threed = None
self._rawbitrate = None
self._resolution = None
self._quality = None
self._dimensions = None
self._bitrate = None
self._extension = None
self.encrypted = None
self._notes = None
self._url = None
self._rawurl = None
self._parent = parent
self._filename = None
self._fsize = None
self._active = False
@property
def rawbitrate(self):
""" Return raw bitrate value. """
return self._rawbitrate
@property
def threed(self):
""" Return bool, True if stream is 3D. """
return self._threed
@property
def itag(self):
""" Return itag value of stream. """
return self._itag
@property
def resolution(self):
""" Return resolution of stream as str. 0x0 if audio. """
return self._resolution
@property
def dimensions(self):
""" Return dimensions of stream as tuple. (0, 0) if audio. """
return self._dimensions
@property
def quality(self):
""" Return quality of stream (bitrate or resolution).
eg, 128k or 640x480 (str)
"""
return self._quality
@property
def title(self):
""" Return YouTube video title as a string. """
return self._parent.title
@property
def extension(self):
""" Return appropriate file extension for stream (str).
Possible values are: 3gp, m4a, m4v, mp4, webm, ogg
"""
return self._extension
@property
def bitrate(self):
""" Return bitrate of an audio stream. """
return self._bitrate
@property
def mediatype(self):
""" Return mediatype string (normal, audio or video).
(normal means a stream containing both video and audio.)
"""
return self._mediatype
@property
def notes(self):
""" Return additional notes regarding the stream format. """
return self._notes
@property
def url(self):
""" Return the url, decrypt if required. """
return self._url
@property
def url_https(self):
""" Return https url. """
return self.url.replace("http://", "https://")
def __repr__(self):
""" Return string representation. """
out = "%s:%s@%s" % (self.mediatype, self.extension, self.quality)
return out
def cancel(self):
""" Cancel an active download. """
if self._active:
self._active = False
return True
def remux(infile, outfile, quiet=False, muxer="ffmpeg"):
""" Remux audio. """
muxer = muxer if isinstance(muxer, str) else "ffmpeg"
for tool in set([muxer, "ffmpeg", "avconv"]):
cmd = [tool, "-y", "-i", infile, "-acodec", "copy", "-vn", outfile]
try:
with open(os.devnull, "w") as devnull:
subprocess.call(cmd, stdout=devnull, stderr=subprocess.STDOUT)
except OSError:
dbg("Failed to remux audio using %s", tool)
else:
os.unlink(infile)
dbg("remuxed audio file using %s" % tool)
if not quiet:
sys.stdout.write("\nAudio remuxed.\n")
break
else:
logging.warning("audio remux failed")
os.rename(infile, outfile)
def get_size_done(bytesdone, progress):
_progress_dict = {'KB': 1024.0, 'MB': 1048576.0, 'GB': 1073741824.0}
return round(bytesdone/_progress_dict.get(progress, 1.0), 2)
def get_status_string(progress):
status_string = (' {:,} ' + progress + ' [{:.2%}] received. Rate: [{:4.0f} '
'KB/s]. ETA: [{:.0f} secs]')
if early_py_version:
status_string = (' {0:} ' + progress + ' [{1:.2%}] received. Rate:'
' [{2:4.0f} KB/s]. ETA: [{3:.0f} secs]')
return status_string

View File

@@ -0,0 +1,183 @@
import sys
import time
import logging
import os
import subprocess
if sys.version_info[:2] >= (3, 0):
# pylint: disable=E0611,F0401,I0011
uni = str
else:
uni = unicode
import youtube_dl
from .backend_shared import BasePafy, BaseStream, remux, get_status_string, get_size_done
dbg = logging.debug
early_py_version = sys.version_info[:2] < (2, 7)
class YtdlPafy(BasePafy):
def __init__(self, *args, **kwargs):
self._ydl_info = None
self._ydl_opts = {'quiet': True, 'prefer_insecure': False, 'no_warnings': True}
ydl_opts = kwargs.get("ydl_opts")
if ydl_opts:
self._ydl_opts.update(ydl_opts)
super(YtdlPafy, self).__init__(*args, **kwargs)
def _fetch_basic(self):
""" Fetch basic data and streams. """
if self._have_basic:
return
with youtube_dl.YoutubeDL(self._ydl_opts) as ydl:
try:
self._ydl_info = ydl.extract_info(self.videoid, download=False)
# Turn into an IOError since that is what pafy previously raised
except youtube_dl.utils.DownloadError as e:
raise IOError(str(e).replace('YouTube said', 'Youtube says'))
if self.callback:
self.callback("Fetched video info")
self._title = self._ydl_info['title']
self._author = self._ydl_info['uploader']
self._rating = self._ydl_info['average_rating']
self._length = self._ydl_info['duration']
self._viewcount = self._ydl_info['view_count']
self._username = self._ydl_info['uploader_id']
self._category = self._ydl_info['categories'][0] if self._ydl_info['categories'] else ''
self._bestthumb = self._ydl_info['thumbnails'][0]['url']
self._bigthumb = "http://i.ytimg.com/vi/%s/mqdefault.jpg" % self.videoid
self._bigthumbhd = "http://i.ytimg.com/vi/%s/hqdefault.jpg" % self.videoid
self.expiry = time.time() + 60 * 60 * 5
self._have_basic = True
def _fetch_gdata(self):
""" Extract gdata values, fetch gdata if necessary. """
if self._have_gdata:
return
item = self._get_video_gdata(self.videoid)['items'][0]
snippet = item['snippet']
self._published = uni(snippet['publishedAt'])
self._description = uni(snippet["description"])
# Note: using snippet.get since some videos have no tags object
self._keywords = [uni(i) for i in snippet.get('tags', ())]
self._have_gdata = True
def _process_streams(self):
""" Create Stream object lists from internal stream maps. """
if not self._have_basic:
self._fetch_basic()
allstreams = [YtdlStream(z, self) for z in self._ydl_info['formats']]
self._streams = [i for i in allstreams if i.mediatype == 'normal']
self._audiostreams = [i for i in allstreams if i.mediatype == 'audio']
self._videostreams = [i for i in allstreams if i.mediatype == 'video']
self._m4astreams = [i for i in allstreams if i.extension == 'm4a']
self._oggstreams = [i for i in allstreams if i.extension == 'ogg']
self._allstreams = allstreams
class YtdlStream(BaseStream):
def __init__(self, info, parent):
super(YtdlStream, self).__init__(parent)
self._itag = info['format_id']
if (info.get('acodec') != 'none' and
info.get('vcodec') == 'none'):
self._mediatype = 'audio'
elif (info.get('acodec') == 'none' and
info.get('vcodec') != 'none'):
self._mediatype = 'video'
else:
self._mediatype = 'normal'
self._threed = info.get('format_note') == '3D'
self._rawbitrate = info.get('abr', 0) * 1024
height = info.get('height') or 0
width = info.get('width') or 0
self._resolution = str(width) + 'x' + str(height)
self._dimensions = width, height
self._bitrate = str(info.get('abr', 0)) + 'k'
self._quality = self._bitrate if self._mediatype == 'audio' else self._resolution
self._extension = info['ext']
self._notes = info.get('format_note') or ''
self._url = info.get('url')
self._info = info
def get_filesize(self):
""" Return filesize of the stream in bytes. Set member variable. """
# Faster method
if 'filesize' in self._info and self._info['filesize'] is not None:
return self._info['filesize']
# Fallback
return super(YtdlStream, self).get_filesize()
def download(self, filepath="", quiet=False, progress="Bytes",
callback=None, meta=False, remux_audio=False):
downloader = youtube_dl.downloader.http.HttpFD(ydl(),
{'http_chunk_size': 10485760})
progress_available = ["KB", "MB", "GB"]
if progress not in progress_available:
progress = "Bytes"
status_string = get_status_string(progress)
def progress_hook(s):
if s['status'] == 'downloading':
bytesdone = s['downloaded_bytes']
total = s['total_bytes']
if s.get('speed') is not None:
rate = s['speed'] / 1024
else:
rate = 0
if s.get('eta') is None:
eta = 0
else:
eta = s['eta']
progress_stats = (get_size_done(bytesdone, progress),
bytesdone*1.0/total, rate, eta)
if not quiet:
status = status_string.format(*progress_stats)
sys.stdout.write("\r" + status + ' ' * 4 + "\r")
sys.stdout.flush()
if callback:
callback(total, *progress_stats)
downloader._progress_hooks = [progress_hook]
if filepath and os.path.isdir(filepath):
filename = self.generate_filename(max_length=256 - len('.temp'))
filepath = os.path.join(filepath, filename)
elif filepath:
pass
else:
filepath = self.generate_filename(meta=meta, max_length=256 - len('.temp'))
infodict = {'url': self.url}
downloader.download(filepath, infodict)
print()
if remux_audio and self.mediatype == "audio":
subprocess.run(['mv', filepath, filepath + '.temp'])
remux(filepath + '.temp', filepath, quiet=quiet, muxer=remux_audio)

View File

@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
Pafy = None
def new(url, basic=True, gdata=False, size=False,
callback=None, ydl_opts=None):
global Pafy
if Pafy is None:
from .backend_youtube_dl import YtdlPafy as Pafy
return Pafy(url, basic, gdata, size, callback, ydl_opts=ydl_opts)