Initial import: Music_Server, MusicFree, catalog-sync
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,133 @@
|
||||
'''
|
||||
Function:
|
||||
Implementation of MusicdlGUI
|
||||
Author:
|
||||
Zhenchao Jin
|
||||
WeChat Official Account (微信公众号):
|
||||
Charles的皮卡丘
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
from PyQt5 import *
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtCore import *
|
||||
from musicdl import musicdl
|
||||
from PyQt5.QtWidgets import *
|
||||
from musicdl.modules.utils.misc import touchdir, sanitize_filepath
|
||||
|
||||
|
||||
'''MusicdlGUI'''
|
||||
class MusicdlGUI(QWidget):
|
||||
def __init__(self):
|
||||
super(MusicdlGUI, self).__init__()
|
||||
# initialize
|
||||
self.setWindowTitle('MusicdlGUI —— Charles的皮卡丘')
|
||||
self.setWindowIcon(QIcon(os.path.join(os.path.dirname(__file__), 'icon.ico')))
|
||||
self.setFixedSize(900, 480)
|
||||
self.initialize()
|
||||
# search sources
|
||||
self.src_names = ['QQMusicClient', 'KuwoMusicClient', 'MiguMusicClient', 'QianqianMusicClient', 'KugouMusicClient', 'NeteaseMusicClient']
|
||||
self.label_src = QLabel('Search Engine:')
|
||||
self.check_boxes = []
|
||||
for src in self.src_names:
|
||||
cb = QCheckBox(src, self)
|
||||
cb.setCheckState(QtCore.Qt.Checked)
|
||||
self.check_boxes.append(cb)
|
||||
# input boxes
|
||||
self.label_keyword = QLabel('Keywords:')
|
||||
self.lineedit_keyword = QLineEdit('尾戒')
|
||||
self.button_keyword = QPushButton('Search')
|
||||
# search results table
|
||||
self.results_table = QTableWidget()
|
||||
self.results_table.setColumnCount(7)
|
||||
self.results_table.setHorizontalHeaderLabels(['ID', 'Singers', 'Songname', 'Filesize', 'Duration', 'Album', 'Source'])
|
||||
self.results_table.horizontalHeader().setStyleSheet("QHeaderView::section{background:skyblue;color:black;}")
|
||||
self.results_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.results_table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
# mouse click menu
|
||||
self.context_menu = QMenu(self)
|
||||
self.action_download = self.context_menu.addAction('Download')
|
||||
# progress bar
|
||||
self.bar_download = QProgressBar(self)
|
||||
self.label_download = QLabel('Download progress:')
|
||||
# grid
|
||||
grid = QGridLayout()
|
||||
grid.addWidget(self.label_src, 0, 0, 1, 1)
|
||||
for idx, cb in enumerate(self.check_boxes): grid.addWidget(cb, 0, idx+1, 1, 1)
|
||||
grid.addWidget(self.label_keyword, 1, 0, 1, 1)
|
||||
grid.addWidget(self.lineedit_keyword, 1, 1, 1, len(self.src_names)-1)
|
||||
grid.addWidget(self.button_keyword, 1, len(self.src_names), 1, 1)
|
||||
grid.addWidget(self.label_download, 2, 0, 1, 1)
|
||||
grid.addWidget(self.bar_download, 2, 1, 1, len(self.src_names))
|
||||
grid.addWidget(self.results_table, 3, 0, len(self.src_names), len(self.src_names)+1)
|
||||
self.grid = grid
|
||||
self.setLayout(grid)
|
||||
# connect
|
||||
self.button_keyword.clicked.connect(self.search)
|
||||
self.results_table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.results_table.customContextMenuRequested.connect(self.mouseclick)
|
||||
self.action_download.triggered.connect(self.download)
|
||||
'''initialize'''
|
||||
def initialize(self):
|
||||
self.search_results = {}
|
||||
self.music_records = {}
|
||||
self.selected_music_idx = -10000
|
||||
self.music_client = None
|
||||
'''mouseclick'''
|
||||
def mouseclick(self):
|
||||
self.context_menu.move(QCursor().pos())
|
||||
self.context_menu.show()
|
||||
'''download'''
|
||||
def download(self):
|
||||
self.selected_music_idx = str(self.results_table.selectedItems()[0].row())
|
||||
song_info = self.music_records.get(self.selected_music_idx)
|
||||
with requests.get(song_info['download_url'], headers=self.music_client.music_clients[song_info['source']].default_download_headers, stream=True, verify=False) as resp:
|
||||
if resp.status_code == 200:
|
||||
total_size, chunk_size, download_size = int(resp.headers['content-length']), 1024, 0
|
||||
touchdir(song_info['work_dir'])
|
||||
download_music_file_path = sanitize_filepath(os.path.join(song_info['work_dir'], song_info['song_name']+'.'+song_info['ext']))
|
||||
with open(download_music_file_path, 'wb') as fp:
|
||||
for chunk in resp.iter_content(chunk_size=chunk_size):
|
||||
if not chunk: continue
|
||||
fp.write(chunk)
|
||||
download_size += len(chunk)
|
||||
self.bar_download.setValue(int(download_size / total_size * 100))
|
||||
QMessageBox().information(self, 'Successful Downloads', f"Finish downloading {song_info['song_name']} by {song_info['singers']}, see {download_music_file_path}")
|
||||
self.bar_download.setValue(0)
|
||||
'''search'''
|
||||
def search(self):
|
||||
self.initialize()
|
||||
# selected music sources
|
||||
music_sources = []
|
||||
for cb in self.check_boxes:
|
||||
if cb.isChecked():
|
||||
music_sources.append(cb.text())
|
||||
# keyword
|
||||
keyword = self.lineedit_keyword.text()
|
||||
# search
|
||||
self.music_client = musicdl.MusicClient(music_sources=music_sources)
|
||||
self.search_results = self.music_client.search(keyword=keyword)
|
||||
# showing
|
||||
count, row = 0, 0
|
||||
for per_source_search_results in self.search_results.values():
|
||||
count += len(per_source_search_results)
|
||||
self.results_table.setRowCount(count)
|
||||
for _, (_, per_source_search_results) in enumerate(self.search_results.items()):
|
||||
for _, per_source_search_result in enumerate(per_source_search_results):
|
||||
for column, item in enumerate([str(row), per_source_search_result['singers'], per_source_search_result['song_name'], per_source_search_result['file_size'], per_source_search_result['duration'], per_source_search_result['album'], per_source_search_result['source']]):
|
||||
self.results_table.setItem(row, column, QTableWidgetItem(item))
|
||||
self.results_table.item(row, column).setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
|
||||
self.music_records.update({str(row): per_source_search_result})
|
||||
row += 1
|
||||
# return
|
||||
return self.search_results
|
||||
|
||||
|
||||
'''tests'''
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
gui = MusicdlGUI()
|
||||
gui.show()
|
||||
sys.exit(app.exec_())
|
||||
@@ -0,0 +1,3 @@
|
||||
requests
|
||||
PyQt5
|
||||
musicdl
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Reference in New Issue
Block a user