#!/usr/bin/env python3 import gi, sys, os 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 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.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('孙晓 - 丹歌惊鸿') 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) layout.put(self.ctrl_box, 48, 300) self.add(layout) self.sync_state(True) def set_background_image(self, filepath): pixbuf = GdkPixbuf.Pixbuf.new_from_file(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 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): 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: 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)