parent
d5be89cffe
commit
b1e164050e
@ -0,0 +1,218 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import tkinter as tk
|
||||||
|
import random
|
||||||
|
import os
|
||||||
|
import pytube
|
||||||
|
import string
|
||||||
|
printable = set(string.printable)
|
||||||
|
import pygame
|
||||||
|
from tkinter import filedialog, simpledialog
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
MUSIC_DIR = './music'
|
||||||
|
|
||||||
|
PYTUBE_STATUS_MAX_TIME = 10
|
||||||
|
|
||||||
|
STATUS_BG_COLOR = '#ffc984'
|
||||||
|
STATUS_BG_COLOR2 = '#e58100'
|
||||||
|
CTRL_BG_COLOR = '#78ffc4'
|
||||||
|
CTRL_BG_COLOR2 = '#00bf6b'
|
||||||
|
TEXT_COLOR = 'white'
|
||||||
|
TEXT_COLOR2 = 'white'
|
||||||
|
PLAYLIST_BG_COLOR = '#9abdff'
|
||||||
|
PLAYLIST_BG_COLOR2 = '#2d76ff'
|
||||||
|
PYTUBE_BG_COLOR = '#ffaac0'
|
||||||
|
PYTUBE_BG_COLOR2 = '#ff386b'
|
||||||
|
|
||||||
|
FRAME_SX_W = 800
|
||||||
|
FRAME_DX_W = 500
|
||||||
|
STATUS_H = 150
|
||||||
|
CTRL_H = 100 #50
|
||||||
|
PLS_H = 300
|
||||||
|
PYTUBE_H = STATUS_H + CTRL_H + PLS_H
|
||||||
|
|
||||||
|
FONT_FRAME = ("clean", 20, "bold")
|
||||||
|
FONT_CTRL_FRAME = ("clean", 15, "bold")
|
||||||
|
FONT_STATUS = ("clean", 16, "bold")
|
||||||
|
FONT_BUTTONS = ("clean", 16, "bold")
|
||||||
|
FONT_LIST = ("clean", 12, "bold")
|
||||||
|
|
||||||
|
HOW_MANY_SEARCH = 25
|
||||||
|
|
||||||
|
class celaigia:
|
||||||
|
def __init__(self, root):
|
||||||
|
self.root = root
|
||||||
|
self.root.title("MusicPlayer")
|
||||||
|
self.root.geometry(f"{FRAME_SX_W+FRAME_DX_W}x{PYTUBE_H}")
|
||||||
|
|
||||||
|
pygame.init()
|
||||||
|
self.mixer = pygame.mixer
|
||||||
|
self.mixer.init()
|
||||||
|
|
||||||
|
self.track = tk.StringVar()
|
||||||
|
self.status = tk.StringVar()
|
||||||
|
self.pystatus = tk.StringVar()
|
||||||
|
self.playlist_folder = tk.StringVar()
|
||||||
|
self.playlist_folder.set('music/default')
|
||||||
|
|
||||||
|
# Crea status frame
|
||||||
|
self.StatusFrame = tk.LabelFrame(self.root, text="Quid Accidit Plaier", font=FONT_FRAME,bg=STATUS_BG_COLOR, fg=TEXT_COLOR2, bd=5, relief=tk.GROOVE)
|
||||||
|
self.StatusFrame.place(x=0, y=0, width=FRAME_SX_W, height=STATUS_H)
|
||||||
|
|
||||||
|
self.songtrack = tk.Label(self.StatusFrame, textvariable=self.track, width=20, font=FONT_STATUS,bg=STATUS_BG_COLOR, fg=TEXT_COLOR).place(x=0,y=0, width=int(FRAME_SX_W/2) ,height=int(STATUS_H/2))
|
||||||
|
self.trackstatus = tk.Label(self.StatusFrame, textvariable=self.status, font=FONT_STATUS,bg=STATUS_BG_COLOR, fg=TEXT_COLOR).place(x=int(FRAME_SX_W/2),y=0, width=int(FRAME_SX_W/2) ,height=int(STATUS_H*0.5))
|
||||||
|
self.pytubestatus = tk.Label(self.StatusFrame, textvariable=self.pystatus, font=FONT_STATUS,bg=STATUS_BG_COLOR, fg=TEXT_COLOR).place(x=0,y=int(STATUS_H/2), width=FRAME_SX_W ,height=int(STATUS_H/2))
|
||||||
|
self.StatusFrame.after(1*PYTUBE_STATUS_MAX_TIME, clear_on_after(self.pystatus))
|
||||||
|
|
||||||
|
# Crea frame per bottoni controlli player
|
||||||
|
self.controlFrame = tk.LabelFrame(self.root, text="Controlly Plaier", font=FONT_CTRL_FRAME, bg=CTRL_BG_COLOR, fg=TEXT_COLOR2, bd=5, relief=tk.GROOVE)
|
||||||
|
self.controlFrame.place(x=0, y=STATUS_H, width=FRAME_SX_W, height=CTRL_H)
|
||||||
|
self.sonabtn = tk.Button(self.controlFrame, text="sona", command=self.play, width=8, height=1,font=FONT_BUTTONS, fg=TEXT_COLOR, bg=CTRL_BG_COLOR2).grid(row=0, column=0, padx=10,pady=5)
|
||||||
|
self.sonatuttebtn = tk.Button(self.controlFrame, text="sona\ntutte", command=self.play_all, width=8, height=1,font=FONT_BUTTONS, fg=TEXT_COLOR, bg=CTRL_BG_COLOR2).grid(row=0, column=4, padx=10, pady=5)
|
||||||
|
self.sonatutterandom = tk.Button(self.controlFrame, text="shuffle\nbaby", command=lambda: self.play_all(shuffle=True), width=8, height=1,font=FONT_BUTTONS, fg=TEXT_COLOR, bg=CTRL_BG_COLOR2).grid(row=0, column=5,padx=10, pady=5)
|
||||||
|
self.pausabtn = tk.Button(self.controlFrame, text="pausa", command=self.pause, width=8, height=1, font=FONT_BUTTONS, fg=TEXT_COLOR, bg=CTRL_BG_COLOR2).grid(row=0, column=1, padx=10, pady=5)
|
||||||
|
self.menopausabtn = tk.Button(self.controlFrame, text="menopausa", command=self.unpause, width=8, height=1, font=FONT_BUTTONS, fg=TEXT_COLOR, bg=CTRL_BG_COLOR2).grid(row=0, column=2, padx=10, pady=5)
|
||||||
|
self.stoppabtn = tk.Button(self.controlFrame, text="stoppa", command=self.stop, width=8, height=1, font=FONT_BUTTONS, fg=TEXT_COLOR, bg=CTRL_BG_COLOR2).grid(row=0, column=3, padx=10,pady=5)
|
||||||
|
|
||||||
|
# Crea Playlist Frame
|
||||||
|
self.playlistFrame = tk.LabelFrame(self.root, text="Playlist", font=FONT_FRAME, bg=PLAYLIST_BG_COLOR, fg=TEXT_COLOR2, bd=5, relief=tk.GROOVE)
|
||||||
|
self.playlistFrame.place(x=0, y= STATUS_H + CTRL_H, width=FRAME_SX_W, height=PLS_H)
|
||||||
|
self.cur_playlist = tk.Label(self.playlistFrame, textvariable=self.playlist_folder, width=20, font=FONT_STATUS,bg=PLAYLIST_BG_COLOR , fg=TEXT_COLOR).place(x=0, y= int(PLS_H*3/4), width=int(FRAME_SX_W/2), height=int(PLS_H/4))
|
||||||
|
self.playlist = tk.Listbox(self.playlistFrame, selectbackground="gold", selectmode=tk.SINGLE, font=FONT_LIST, bg=PLAYLIST_BG_COLOR , fg=TEXT_COLOR, bd=5, relief=tk.GROOVE)
|
||||||
|
self.playlist.place(x=0, y=0 ,width=FRAME_SX_W,height=int(PLS_H*3/4))
|
||||||
|
self.create_playlist_btn = tk.Button(self.playlistFrame, text="Crea\nPlaylist", font=FONT_BUTTONS,bg=PLAYLIST_BG_COLOR2, fg=TEXT_COLOR,width=40, height=5,command=self.create_playlist)
|
||||||
|
self.create_playlist_btn.place(x=int(FRAME_SX_W/2), y=int(PLS_H*3/4)-5, width = int(FRAME_SX_W/6), height=int(PLS_H/4))
|
||||||
|
self.choose_playlist_btn = tk.Button(self.playlistFrame, text="Carica\nPlaylist",font=FONT_BUTTONS, bg=PLAYLIST_BG_COLOR2, fg=TEXT_COLOR,width=40, height=5, command=lambda: self.choose_playlist(kind='scratch'))
|
||||||
|
self.choose_playlist_btn.place(x=int(FRAME_SX_W*2/3) , y = int(PLS_H*3/4)-5, width= int(FRAME_SX_W/6), height=int(PLS_H/4))
|
||||||
|
self.add_playlist_btn = tk.Button(self.playlistFrame, text="Aggiungi\nPlaylist",font=FONT_BUTTONS, bg=PLAYLIST_BG_COLOR2, fg=TEXT_COLOR,width=40, height=5,command=lambda: self.choose_playlist(kind='add'))
|
||||||
|
self.add_playlist_btn.place(x=int(FRAME_SX_W*5/6), y=int(PLS_H*3/4)-5, width= int(FRAME_SX_W/6), height=int(PLS_H/4))
|
||||||
|
|
||||||
|
# Crea pytube frame
|
||||||
|
self.pytubeFrame = tk.LabelFrame(self.root, text="Pytube", font=FONT_FRAME, bg=PYTUBE_BG_COLOR,fg=TEXT_COLOR2, bd=5, relief=tk.GROOVE)
|
||||||
|
self.pytubeFrame.place(x=FRAME_SX_W, y=0, width=FRAME_DX_W, height=PYTUBE_H)
|
||||||
|
tk.Label(self.pytubeFrame, text='cerca suittubo qua sotto,\n seleziona + invio per scarècar \nnella cartella/playlist curiente',font=FONT_STATUS,fg=TEXT_COLOR, bg=PYTUBE_BG_COLOR).place(x=0, y=0, width=FRAME_DX_W, height=int(PYTUBE_H/6))
|
||||||
|
self.search_entry = tk.Entry(self.pytubeFrame)
|
||||||
|
self.search_entry.bind('<Return>', self.ytsearch)
|
||||||
|
self.search_entry.place(x=0, y=int(PYTUBE_H/6),width=FRAME_DX_W,height=int(PYTUBE_H/6))
|
||||||
|
self.search_list = tk.Listbox(self.pytubeFrame, font=FONT_LIST,fg=TEXT_COLOR, bg=PYTUBE_BG_COLOR, selectmode=tk.SINGLE)
|
||||||
|
pos = 0
|
||||||
|
for _ in range(HOW_MANY_SEARCH):
|
||||||
|
item = ' x x x y y y z z z'
|
||||||
|
self.search_list.insert(pos, item)
|
||||||
|
pos += 1
|
||||||
|
self.search_list.bind('<Return>', self.ytdownload)
|
||||||
|
self.search_list.place(x=0,y=int(PYTUBE_H/3),width=FRAME_DX_W,height=int(PYTUBE_H*2/3))
|
||||||
|
# usa db dio db
|
||||||
|
self.track_paths = {}
|
||||||
|
self.update_playlist(kind='scratch')
|
||||||
|
|
||||||
|
|
||||||
|
def create_playlist(self):
|
||||||
|
self.playlist_folder.set(MUSIC_DIR + '/' + tk.simpledialog.askstring(parent=self.playlistFrame, prompt="nome playlist:",title='acchitta playlist'))
|
||||||
|
self.update_playlist(kind='scratch')
|
||||||
|
|
||||||
|
def choose_playlist(self,kind):
|
||||||
|
self.playlist_folder.set(tk.filedialog.askdirectory(parent=self.playlistFrame, initialdir=MUSIC_DIR,title='scegli una playlist (aka una cartella)'))
|
||||||
|
self.update_playlist(kind)
|
||||||
|
|
||||||
|
def update_playlist(self,kind, folder=None):
|
||||||
|
if folder==None:
|
||||||
|
folder = self.playlist_folder.get()
|
||||||
|
if not os.path.isdir(self.playlist_folder.get()):
|
||||||
|
os.makedirs(self.playlist_folder.get())
|
||||||
|
if kind =='add':
|
||||||
|
for track in os.listdir(folder):
|
||||||
|
if ismusic(track) & (track not in self.playlist.get(0,tk.END)):
|
||||||
|
self.playlist.insert(tk.END, track)
|
||||||
|
self.track_paths[track] = f"{folder}/{track}"
|
||||||
|
elif kind == 'scratch':
|
||||||
|
self.playlist.delete(0,tk.END)
|
||||||
|
pos = 0
|
||||||
|
for track in os.listdir(folder):
|
||||||
|
if ismusic(track):
|
||||||
|
self.playlist.insert(pos, track)
|
||||||
|
self.track_paths[track] = f"{folder}/{track}"
|
||||||
|
pos += 1
|
||||||
|
|
||||||
|
def play_all(self, shuffle=False):
|
||||||
|
if shuffle:
|
||||||
|
songtracks = list(self.playlist.get(0,tk.END))
|
||||||
|
random.shuffle(songtracks)
|
||||||
|
self.playlist.delete(0,tk.END)
|
||||||
|
for i,track in enumerate(songtracks):
|
||||||
|
self.playlist.insert(i,track)
|
||||||
|
del songtracks
|
||||||
|
self.play(self.track_paths[self.playlist.get(0)])
|
||||||
|
for ti in self.playlist.get(1,tk.END):
|
||||||
|
self.mixer.music.queue(self.track_paths[ti])
|
||||||
|
|
||||||
|
def play(self,what='selezionato'):
|
||||||
|
if what=='selezionato':
|
||||||
|
self.track.set(self.playlist.get(tk.ACTIVE))
|
||||||
|
else:
|
||||||
|
self.track.set(what.split('/')[-1])
|
||||||
|
self.status.set("- sta sònando")
|
||||||
|
self.mixer.music.load(self.track_paths[self.track.get()])
|
||||||
|
self.mixer.music.play()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.track.set('')
|
||||||
|
self.status.set("stop, dimenticami stupidu")
|
||||||
|
self.mixer.music.stop()
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
self.status.set("- la meccanica non mi interessa, siamo in pausa")
|
||||||
|
self.mixer.music.pause()
|
||||||
|
|
||||||
|
def unpause(self):
|
||||||
|
self.status.set("- sta sònando")
|
||||||
|
self.mixer.music.unpause()
|
||||||
|
|
||||||
|
def ytsearch(self,event):
|
||||||
|
self.search_list.delete(0, 2) # entrambi gli estremi compresi..
|
||||||
|
self.yt_results = {pulisci_stringa(r.title): r.watch_url for r in pytube.Search(self.search_entry.get()).results[:HOW_MANY_SEARCH]}
|
||||||
|
pos = 0
|
||||||
|
self.pystatus.set(f'cerco: {self.search_entry.get()}')
|
||||||
|
for item in self.yt_results.keys():
|
||||||
|
try:
|
||||||
|
self.search_list.insert(pos, item)
|
||||||
|
pos += 1
|
||||||
|
except:
|
||||||
|
1
|
||||||
|
|
||||||
|
def ytdownload(self,event):
|
||||||
|
#wannabe: scegli formato (wav,ogg ecc) e tipo (audio/video)
|
||||||
|
name = self.search_list.get(tk.ACTIVE)
|
||||||
|
url = self.yt_results[name]
|
||||||
|
stream = pytube.YouTube(url).streams.filter(only_audio=True).first()
|
||||||
|
self.pystatus.set(f'scarico: {self.search_entry.get()}')
|
||||||
|
stream.download(self.playlist_folder.get(),filename=f"{name}.mp4")
|
||||||
|
if os.path.isfile(f"{self.playlist_folder.get()}/{name}.mp4"):
|
||||||
|
tmp_file = f'{self.playlist_folder.get()}/{name}.mp4'
|
||||||
|
self.pystatus.set(f'converto: {self.search_entry.get()}')
|
||||||
|
bash(f"ffmpeg -i {tmp_file} -vn -acodec libvorbis -y {tmp_file[:-4]}.ogg")
|
||||||
|
bash(f"rm {self.playlist_folder.get()}/{name}.mp4")
|
||||||
|
self.pystatus.set('')
|
||||||
|
self.playlist.insert(tk.END,name)
|
||||||
|
self.track_paths[name]=f"{self.playlist_folder}/{name}"
|
||||||
|
|
||||||
|
def pulisci_stringa(s,kind='printable'):
|
||||||
|
if kind=='printable':
|
||||||
|
s = ''.join(filter(lambda x: x in '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ', s))
|
||||||
|
else:
|
||||||
|
print(f'ma che kind stai a dì {kind}',flush=True)
|
||||||
|
return s.replace(' ','_')
|
||||||
|
|
||||||
|
def ismusic(file):
|
||||||
|
return file.split('.')[-1] in ['mp3', 'ogg', 'flac', 'wav']
|
||||||
|
|
||||||
|
def clear_on_after(var):
|
||||||
|
var.set("")
|
||||||
|
|
||||||
|
def bash(cmd):
|
||||||
|
subprocess.call(['/bin/bash', '-c', cmd])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = tk.Tk()
|
||||||
|
celaigia(app)
|
||||||
|
app.mainloop()
|
@ -0,0 +1,3 @@
|
|||||||
|
pytube==11.0.1
|
||||||
|
pygame==2.0.1
|
||||||
|
|
Loading…
Reference in New Issue