1# Copyright (C) 2012-13 Nick Boultbee, Thomas Vogt 2# Copyright (C) 2008 Andreas Bombe 3# Copyright (C) 2005 Michael Urman 4# Based on osd.py (C) 2005 Ton van den Heuvel, Joe Wreshnig 5# (C) 2004 Gustavo J. A. M. Carneiro 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11 12from gi.repository import Gtk, Gdk 13 14from quodlibet import _ 15from quodlibet import app 16from quodlibet import qltk 17from quodlibet.util import connect_obj 18from quodlibet.formats import DUMMY_SONG 19from quodlibet.qltk.textedit import PatternEdit 20from quodlibet.qltk import Icons 21 22 23class ConfigLabel(Gtk.Label): 24 """Customised Label for configuration, tied to a widget""" 25 26 def __init__(self, text, widget): 27 super(Gtk.Label, self).__init__(label=text, use_underline=True) 28 self.set_mnemonic_widget(widget) 29 self.set_alignment(0.0, 0.5) 30 31 32class AnimOsdPrefs(Gtk.VBox): 33 34 def __init__(self, plugin): 35 super(AnimOsdPrefs, self).__init__(spacing=6) 36 37 self.Conf = plugin.Conf 38 self.plugin = plugin 39 40 def __coltofloat(x): 41 return x / 65535.0 42 43 def __floattocol(x): 44 return int(x * 65535) 45 46 def show_preview(): 47 preview_song = (app.player.song if app.player.song else DUMMY_SONG) 48 self.plugin.plugin_on_song_started(preview_song) 49 50 def on_button_pressed(x=None, y=None): 51 show_preview() 52 53 def set_text(button): 54 color = button.get_color() 55 color = map(__coltofloat, 56 (color.red, color.green, color.blue, 0.0)) 57 self.Conf.text = tuple(color) 58 show_preview() 59 60 def set_fill(button): 61 color = button.get_color() 62 color = map(__coltofloat, (color.red, color.green, color.blue, 63 button.get_alpha())) 64 self.Conf.fill = tuple(color) 65 show_preview() 66 67 def set_font(button): 68 font = button.get_font_name() 69 self.Conf.font = font 70 show_preview() 71 72 def change_delay(button): 73 value = int(button.get_value() * 1000) 74 self.Conf.delay = value 75 76 def change_monitor(button): 77 """Monitor number config change handler""" 78 value = int(button.get_value()) 79 self.Conf.monitor = value 80 show_preview() 81 82 def change_position(button, x, y): 83 self.Conf.pos_x = x / 2.0 84 self.Conf.pos_y = y / 2.0 85 show_preview() 86 87 def change_align(button): 88 value = button.get_active() 89 self.Conf.align = value 90 show_preview() 91 92 def change_shadow(button): 93 if button.get_active(): 94 self.Conf.shadow = (0.0, 0.0, 0.0, self.Conf.fill[3]) 95 else: 96 self.Conf.shadow = (-1.0, 0.0, 0.0, 0.0) 97 show_preview() 98 99 def change_outline(button): 100 if button.get_active(): 101 # Vary with fill alpha to create a smoother outline edge 102 alpha = (min(1.0, self.Conf.fill[3] * 1.25)) 103 self.Conf.outline = (0.1, 0.1, 0.1, alpha) 104 else: 105 self.Conf.outline = (-1.0, 0.0, 0.0) 106 show_preview() 107 108 def change_rounded(button): 109 if button.get_active(): 110 self.Conf.corners = 1 111 else: 112 self.Conf.corners = 0 113 show_preview() 114 115 def change_coversize(button): 116 value = int(button.get_value()) 117 self.Conf.coversize = value 118 show_preview() 119 120 def edit_pattern(button): 121 w = PatternEdit(button, self.Conf.string) 122 w.set_default_size(520, 260) 123 w.text = self.Conf.string 124 connect_obj(w.apply, 'clicked', set_string, w) 125 w.show() 126 127 def set_string(window): 128 value = window.text 129 self.Conf.string = value 130 show_preview() 131 132 def build_display_widget(): 133 vb2 = Gtk.VBox(spacing=3) 134 hb = Gtk.HBox(spacing=6) 135 # Set monitor to display OSD on if there's more than one 136 monitor_cnt = Gdk.Screen.get_default().get_n_monitors() 137 if monitor_cnt > 1: 138 adj = Gtk.Adjustment(value=self.Conf.monitor, lower=0, 139 upper=monitor_cnt - 1, step_increment=1) 140 monitor = Gtk.SpinButton(adjustment=adj) 141 monitor.set_numeric(True) 142 monitor.connect('value-changed', change_monitor) 143 l2 = ConfigLabel("_Monitor:", monitor) 144 hb.pack_start(l2, False, True, 0) 145 hb.pack_start(monitor, False, True, 0) 146 vb2.pack_start(hb, True, True, 0) 147 else: 148 # should be this by default anyway 149 self.Conf.monitor = 0 150 151 hb = Gtk.HBox(spacing=6) 152 grid = Gtk.Grid(column_homogeneous=True, 153 row_homogeneous=True, 154 row_spacing=4, 155 column_spacing=4) 156 arrows = [['↖', '↑', '↗'], 157 ['←', '○', '→'], 158 ['↙', '↓', '↘ ']] 159 160 group = None 161 for x in range(3): 162 for y in range(3): 163 rb = Gtk.RadioButton(group=group, label=arrows[y][x]) 164 if (int(self.Conf.pos_x * 2.0) == x and 165 int(self.Conf.pos_y * 2.0) == y): 166 rb.set_active(True) 167 grid.attach(rb, x, y, 1, 1) 168 group = rb 169 170 # Connect to signal after the correct radio button has been 171 # selected 172 for x in range(3): 173 for y in range(3): 174 rb = grid.get_child_at(x, y) 175 rb.connect('toggled', change_position, x, y) 176 177 lbl = ConfigLabel(_("_Position:"), grid) 178 hb.pack_start(lbl, False, True, 0) 179 hb.pack_start(grid, False, True, 0) 180 vb2.pack_start(hb, False, True, 6) 181 182 hb = Gtk.HBox(spacing=6) 183 coversize = Gtk.SpinButton( 184 adjustment=Gtk.Adjustment.new( 185 self.Conf.coversize, 1, 600, 1, 10, 0), 186 climb_rate=1, digits=0) 187 coversize.set_numeric(True) 188 coversize.connect('value-changed', change_coversize) 189 l1 = ConfigLabel(_("_Cover size:"), coversize) 190 hb.pack_start(l1, False, True, 0) 191 hb.pack_start(coversize, False, True, 0) 192 vb2.pack_start(hb, False, True, 0) 193 return vb2 194 195 frame = qltk.Frame(label=_("Display"), child=build_display_widget()) 196 frame.set_border_width(6) 197 self.pack_start(frame, False, True, 0) 198 199 def build_text_widget(): 200 t = Gtk.Table(n_rows=2, n_columns=2) 201 t.props.expand = False 202 t.set_col_spacings(6) 203 t.set_row_spacings(3) 204 205 font = Gtk.FontButton(show_style=True) 206 font.set_font_name(self.Conf.font) 207 font.connect('font-set', set_font) 208 lbl = ConfigLabel(_("_Font:"), font) 209 t.attach(lbl, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) 210 t.attach(font, 1, 2, 0, 1) 211 212 align = Gtk.ComboBoxText() 213 align.append_text(_("Left")) 214 align.append_text(_("Center")) 215 align.append_text(_("Right")) 216 align.set_active(self.Conf.align) 217 align.connect('changed', change_align) 218 lbl = ConfigLabel(_("_Align text:"), align) 219 220 t.attach(lbl, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) 221 t.attach(align, 1, 2, 1, 2) 222 return t 223 224 frame = qltk.Frame(label=_("Text"), child=build_text_widget()) 225 frame.set_border_width(6) 226 self.pack_start(frame, False, True, 0) 227 228 def build_colors_widget(): 229 t = Gtk.Table(n_rows=2, n_columns=2) 230 t.props.expand = False 231 t.set_col_spacings(6) 232 t.set_row_spacings(3) 233 b = Gtk.ColorButton( 234 rgba=Gdk.RGBA(*map(__floattocol, self.Conf.text))) 235 l = ConfigLabel(_("_Text:"), b) 236 237 t.attach(l, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL) 238 t.attach(b, 1, 2, 0, 1) 239 b.connect('color-set', set_text) 240 b = Gtk.ColorButton(color=Gdk.Color(*map(__floattocol, 241 self.Conf.fill[0:3]))) 242 b.set_use_alpha(True) 243 b.set_alpha(__floattocol(self.Conf.fill[3])) 244 b.connect('color-set', set_fill) 245 l = ConfigLabel(_("_Fill:"), b) 246 t.attach(l, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) 247 t.attach(b, 1, 2, 1, 2) 248 return t 249 250 f = qltk.Frame(label=_("Colors"), child=build_colors_widget()) 251 f.set_border_width(6) 252 self.pack_start(f, False, False, 0) 253 254 def build_effects_widget(): 255 vb2 = Gtk.VBox(spacing=3) 256 hb = Gtk.HBox(spacing=6) 257 toggles = [ 258 (_("_Shadows"), self.Conf.shadow[0], change_shadow), 259 (_("_Outline"), self.Conf.outline[0], change_outline), 260 (_("Rou_nded Corners"), self.Conf.corners - 1, change_rounded)] 261 262 for (label, current, callback) in toggles: 263 checkb = Gtk.CheckButton(label=label, use_underline=True) 264 checkb.set_active(current != -1) 265 checkb.connect("toggled", callback) 266 hb.pack_start(checkb, True, True, 0) 267 vb2.pack_start(hb, True, True, 0) 268 269 hb = Gtk.HBox(spacing=6) 270 timeout = Gtk.SpinButton( 271 adjustment=Gtk.Adjustment.new( 272 self.Conf.delay / 1000.0, 0, 60, 0.1, 1.0, 0), 273 climb_rate=0.1, digits=1) 274 timeout.set_numeric(True) 275 timeout.connect('value-changed', change_delay) 276 l1 = ConfigLabel(_("_Delay:"), timeout) 277 hb.pack_start(l1, False, True, 0) 278 hb.pack_start(timeout, False, True, 0) 279 vb2.pack_start(hb, False, True, 0) 280 return vb2 281 282 frame = qltk.Frame(label=_("Effects"), child=build_effects_widget()) 283 frame.set_border_width(6) 284 self.pack_start(frame, False, True, 0) 285 286 def build_buttons_widget(): 287 hb = Gtk.HBox(spacing=6) 288 edit_button = qltk.Button(_(u"Ed_it Display Pattern…"), 289 Icons.EDIT) 290 edit_button.connect('clicked', edit_pattern) 291 hb.pack_start(edit_button, False, True, 0) 292 preview_button = Gtk.Button(label=_("Preview")) 293 preview_button.connect("button-press-event", on_button_pressed) 294 hb.pack_start(preview_button, False, True, 0) 295 return hb 296 297 self.pack_start(build_buttons_widget(), False, True, 0) 298