sonist-gtk/window.py

239 lines
5.4 KiB
Python

#!/usr/bin/env python3
import gi, sys, os, mutagen
from pprint import pprint as print
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib, GdkPixbuf
from utils import blur_image, base64_to_pixbuf
from ui.image import ScaleImage
from ui.slider import Slider
from ui.image_button import ImageButton
from ui.text import TextBox
from ui.ctrl_box import CtrlBox
class SonistWindow(Gtk.Window):
def __init__(self, app):
Gtk.Window.__init__(self)
self.app = app
self.connect("destroy", self.quit)
self.app.connect('state_changed', lambda a, x: self.update_play_stat(x == 'play'))
self.app.connect('song_changed', lambda a, id: self.sync_state(False))
self.set_name('SonistWindow')
self.set_default_size(320, 384)
self.set_resizable(False)
self.set_wmclass('Sonist', 'Sonist')
self.set_opacity(0.9)
# self.set_keep_above(True)
# album_img = './usr/share/sonist/album.png'
album_img = './usr/share/sonist/avatar.jpg'
self.set_background_image(album_img)
layout = Gtk.Layout()
# 菜单按钮
menu = ImageButton('./usr/share/sonist/menu.png')
layout.put(menu, 276, 6)
# 唱片
disk = ScaleImage('./usr/share/sonist/disk.png')
handler = ScaleImage('./usr/share/sonist/handler.png')
album = ScaleImage(album_img)
disk.resize(192, 192)
album.resize(128, 128).set_radius(64)
handler.resize(48, 96)
self.handler = handler
self.album = album
box = Gtk.Fixed()
box.put(disk, 16, 16)
box.put(album, 48, 48)
box.put(handler, 0, 16)
layout.put(box, 48, 16)
# title
# self.title_box = TextBox(256, 20)
self.title_box = Gtk.Label()
self.title_box.set_text('mpd loading...')
layout.put(self.title_box, 32, 244)
# 播放进度
slider = Slider(272)
layout.put(slider, 24, 270)
# 控制条
self.ctrl_box = CtrlBox()
self.ctrl_box.connect('clicked', self.ctrl_clicked)
self.ctrl_box.disabled = not self.app.mpd_is_online
layout.put(self.ctrl_box, 48, 300)
self.add(layout)
self.sync_state(True)
def set_background_image(self, filepath):
if type(filepath) == str:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(filepath)
else:
pixbuf = filepath
pixbuf = blur_image(pixbuf)
pixbuf.savev(f"/tmp/sonist_album_cache", 'png', [], [])
css = f"""
#SonistWindow {{
background-image: url('/tmp/sonist_album_cache');
background-size: 100% 100%;
background-position: center;
}}
"""
# 加载CSS样式
css_provider = Gtk.CssProvider()
css_provider.load_from_data(css.encode('UTF-8'))
context = Gtk.StyleContext()
screen = Gdk.Screen.get_default()
context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
def ctrl_clicked(self, box, btn):
match(btn):
case 'play_btn':
self.toggle_play()
case 'mode_btn':
# repeat all
if self.ctrl_box.curr_mode == 0:
self.app.mpd.repeat(1)
self.app.mpd.random(0)
self.app.mpd.single(0)
# random
elif self.ctrl_box.curr_mode == 1:
self.app.mpd.repeat(0)
self.app.mpd.random(1)
self.app.mpd.single(0)
# single
else:
self.app.mpd.repeat(0)
self.app.mpd.random(0)
self.app.mpd.single(1)
case 'prev_btn':
self.prev_song()
case 'next_btn':
self.next_song()
case 'vol_btn':
self.toggle_play()
def toggle_play(self):
if self.stat.get('state') == 'stop':
self.app.mpd.play()
else:
self.app.mpd.pause()
self.sync_state()
self.update_play_stat(self.stat.get('state') == 'play')
def prev_song(self):
self.app.mpd.previous()
self.sync_state()
def next_song(self):
self.app.mpd.next()
self.sync_state()
def update_play_stat(self, played = True):
if not self.app.mpd_is_online:
return
if played:
self.handler.reset('./usr/share/sonist/handler_a.png')
else:
self.handler.reset('./usr/share/sonist/handler.png')
# 切换播放按钮状态
self.ctrl_box.toggle_play_btn(played)
def sync_state(self, first = False):
if not self.app.mpd_is_online:
return
self.stat = self.app.mpd.status()
played = self.stat.get('state')
song = self.app.mpd.currentsong()
if first:
self.update_play_stat(played == 'play')
if self.stat.get('single') == '1':
self.ctrl_box.toggle_mode_btn(mode = 'single')
elif self.stat.get('random') == '1':
self.ctrl_box.toggle_mode_btn(mode = 'random')
# 更新歌曲信息
self.title_box.set_text("%s - %s" % (song.get('artist'), song.get('title')))
filepath = f"./album/{song['title']}.png"
# print(self.stat)
# print(song)
if os.path.isfile(filepath):
self.update_album(filepath)
else:
pass
# audio = mutagen.File()
# buff = self.app.get_cover(song, filepath, self.update_album)
# print(buff)
# with open(filepath, 'wb') as file:
# output = file.write(buff)
# self.set_background_image(filepath)
# print(self.app.mpd.readpicture(self.stat.get('songid')))
def update_album(self, filepath):
self.set_background_image(filepath)
self.album.reset(filepath).set_radius(64)
def quit(self, win):
self.app.remove_window(self)
python + gtk3开发的基于mpd后端的音乐播放器
Python 99.1%
Shell 0.9%