Guest User

Untitled

a guest
Jul 2nd, 2018
653
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.46 KB | None | 0 0
  1. # desktopcover - displays Exaile album covers on the desktop
  2. # Copyright (C) 2006-2007 Johannes Sasongko <sasongko@gmail.com>
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License along
  15. # with this program; if not, write to the Free Software Foundation, Inc.,
  16. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17.  
  18. import gobject, gtk
  19. from gettext import gettext as _
  20. from xl import xlmisc
  21. import xl.plugins as plugins
  22.  
  23. PLUGIN_NAME = _("Desktop Cover")
  24. PLUGIN_AUTHORS = ["Johannes Sasongko <sasongko@gmail.com>",
  25. "Adam Olsen <arolsen@gmail.com>"]
  26.  
  27. PLUGIN_VERSION = "0.3.3"
  28. PLUGIN_DESCRIPTION = _("Displays the current album cover on the desktop")
  29. PLUGIN_ENABLED = False
  30. PLUGIN_ICON = None
  31.  
  32. PLUGIN = None
  33. CONNS = plugins.SignalContainer()
  34.  
  35. class CoverDisplay:
  36. DEFAULT_X = DEFAULT_Y = 0
  37. DEFAULT_WIDTH = DEFAULT_HEIGHT = 200
  38. GRAVITY_SIGNS = {
  39. gtk.gdk.GRAVITY_NORTH_WEST: ('+', '+'),
  40. gtk.gdk.GRAVITY_NORTH_EAST: ('-', '+'),
  41. gtk.gdk.GRAVITY_SOUTH_WEST: ('+', '-'),
  42. gtk.gdk.GRAVITY_SOUTH_EAST: ('-', '-'),
  43. }
  44.  
  45. def __init__(self):
  46. self.window = wnd = gtk.Window()
  47. wnd.set_accept_focus(False)
  48. wnd.set_decorated(False)
  49. #wnd.set_keep_below(True)
  50. wnd.set_resizable(False)
  51. wnd.set_role(__file__)
  52. wnd.set_skip_pager_hint(True)
  53. wnd.set_skip_taskbar_hint(True)
  54. wnd.set_title("")
  55. #wnd.stick()
  56.  
  57. self.x = self.DEFAULT_X
  58. self.y = self.DEFAULT_Y
  59. self.width = self.DEFAULT_WIDTH
  60. self.height = self.DEFAULT_HEIGHT
  61. self.cover = None
  62. self.set_use_image_size()
  63. self.set_keep_center()
  64.  
  65. self.image = img = gtk.Image()
  66. wnd.add(img)
  67. img.show()
  68.  
  69. def set_keep_center(self, keep_center=True):
  70. self.keep_center = keep_center
  71. xlmisc.finish()
  72. if keep_center:
  73. self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
  74. else:
  75. self.window.set_position(gtk.WIN_POS_NONE)
  76. self.set_position()
  77.  
  78. def set_gravity(self, gravity):
  79. xlmisc.finish()
  80. self.window.set_gravity(gravity)
  81.  
  82. def set_position(self, x=None, y=None, force=False):
  83. if x is None or y is None:
  84. x = self.x
  85. y = self.y
  86. else:
  87. self.x = x
  88. self.y = y
  89.  
  90. xlmisc.finish()
  91. if not self.keep_center and (force or self.window.props.visible):
  92. xsgn, ysgn = self.GRAVITY_SIGNS[self.window.get_gravity()]
  93. xlmisc.finish()
  94. self.window.parse_geometry('%s%s%s%s' % (xsgn, x, ysgn, y))
  95.  
  96. def set_use_image_size(self, use_image_size=True):
  97. self.use_image_size = use_image_size
  98.  
  99. def set_size(self, width, height):
  100. self.width = width
  101. self.height = height
  102. self.display(self.cover)
  103.  
  104. def display(self, cover):
  105. self.cover = cover
  106. if cover is None:
  107. self.image.clear()
  108. xlmisc.finish()
  109. self.window.hide()
  110. return
  111.  
  112. pixbuf = gtk.gdk.pixbuf_new_from_file(cover)
  113. width = pixbuf.get_width()
  114. height = pixbuf.get_height()
  115. if not self.use_image_size:
  116. origw = float(width)
  117. origh = float(height)
  118. width, height = self.width, self.height
  119. scale = min(width / origw, height / origh)
  120. width = int(origw * scale)
  121. height = int(origh * scale)
  122. pixbuf = pixbuf.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
  123. self.image.set_from_pixbuf(pixbuf)
  124.  
  125. wnd = self.window
  126. self.set_position(force=True)
  127. xlmisc.finish()
  128. if not wnd.props.visible:
  129. wnd.show()
  130. # May be reset by the WM.
  131. wnd.set_keep_below(True)
  132. wnd.stick()
  133.  
  134. def destroy(self):
  135. self.window.destroy()
  136.  
  137. GRAVITIES = [
  138. # TRANSLATORS: Desktop cover gravity
  139. (_("Northwest"), gtk.gdk.GRAVITY_NORTH_WEST),
  140. # TRANSLATORS: Desktop cover gravity
  141. (_("Northeast"), gtk.gdk.GRAVITY_NORTH_EAST),
  142. # TRANSLATORS: Desktop cover gravity
  143. (_("Southwest"), gtk.gdk.GRAVITY_SOUTH_WEST),
  144. # TRANSLATORS: Desktop cover gravity
  145. (_("Southeast"), gtk.gdk.GRAVITY_SOUTH_EAST),
  146. ]
  147.  
  148. class DesktopCoverConfig(plugins.PluginConfigDialog):
  149. def __init__(self, exaile, title, plugin, plugin_name):
  150. super(type(self), self).__init__(exaile.window, title)
  151. self.exaile = exaile
  152. settings = exaile.settings
  153. self.plugin = plugin
  154. self.plugin_name = plugin_name
  155.  
  156. table = gtk.Table(6, 2)
  157. table.set_border_width(12)
  158. table.set_col_spacings(6)
  159. self.main.add(table)
  160.  
  161. self.position_widgets = position_widgets = []
  162. self.size_widgets = size_widgets = []
  163.  
  164. n_rows = 0
  165.  
  166. self.position_check = check = gtk.CheckButton(_("Manual positioning"))
  167. table.attach(check, 0, 2, n_rows, n_rows + 1)
  168. check.connect('toggled', self._positioning_toggled)
  169. check.set_active(not settings.get_boolean('keep_center',
  170. default=True, plugin=plugin_name))
  171. n_rows += 1
  172.  
  173. label = gtk.Label(_("Gravity"))
  174. table.attach(label, 0, 1, n_rows, n_rows + 1)
  175. position_widgets.append(label)
  176. self.gravity_combo = combo = gtk.combo_box_new_text()
  177. table.attach(combo, 1, 2, n_rows, n_rows + 1)
  178. position_widgets.append(combo)
  179. for grav in GRAVITIES:
  180. combo.append_text(grav[0])
  181. combo.set_active(settings.get_int('gravity', default=0,
  182. plugin=plugin_name))
  183. n_rows += 1
  184.  
  185. # TRANSLATORS: Offset from the desktop border
  186. label = gtk.Label(_("X offset"))
  187. table.attach(label, 0, 1, n_rows, n_rows + 1)
  188. position_widgets.append(label)
  189. x = settings.get_int('x', default=CoverDisplay.DEFAULT_X,
  190. plugin=plugin_name)
  191. adj = gtk.Adjustment(x, 0, 32767, 1, 10, 10)
  192. self.x_spin = spin = gtk.SpinButton(adj)
  193. table.attach(spin, 1, 2, n_rows, n_rows + 1)
  194. position_widgets.append(spin)
  195. n_rows += 1
  196.  
  197. # TRANSLATORS: Offset from the desktop border
  198. label = gtk.Label(_("Y offset"))
  199. table.attach(label, 0, 1, n_rows, n_rows + 1)
  200. position_widgets.append(label)
  201. y = settings.get_int('y', default=CoverDisplay.DEFAULT_Y,
  202. plugin=plugin_name)
  203. adj = gtk.Adjustment(y, 0, 32767, 1, 10, 10)
  204. self.y_spin = spin = gtk.SpinButton(adj)
  205. position_widgets.append(spin)
  206. table.attach(spin, 1, 2, n_rows, n_rows + 1)
  207. n_rows += 1
  208.  
  209. self.sizing_check = check = gtk.CheckButton(_("Manual sizing"))
  210. table.attach(check, 0, 2, n_rows, n_rows + 1)
  211. check.connect('toggled', self._sizing_toggled)
  212. check.set_active(not settings.get_boolean('use_image_size',
  213. default=True, plugin=plugin_name))
  214. n_rows += 1
  215.  
  216. label = gtk.Label(_("Width"))
  217. table.attach(label, 0, 1, n_rows, n_rows + 1)
  218. size_widgets.append(label)
  219. w = settings.get_int('width', default=CoverDisplay.DEFAULT_WIDTH,
  220. plugin=plugin_name)
  221. adj = gtk.Adjustment(w, 0, 32767, 1, 10, 10)
  222. self.width_spin = spin = gtk.SpinButton(adj)
  223. table.attach(spin, 1, 2, n_rows, n_rows + 1)
  224. size_widgets.append(spin)
  225. n_rows += 1
  226.  
  227. label = gtk.Label(_("Height"))
  228. table.attach(label, 0, 1, n_rows, n_rows + 1)
  229. size_widgets.append(label)
  230. h = settings.get_int('height', default=CoverDisplay.DEFAULT_HEIGHT,
  231. plugin=plugin_name)
  232. adj = gtk.Adjustment(h, 0, 32767, 1, 10, 10)
  233. self.height_spin = spin = gtk.SpinButton(adj)
  234. table.attach(spin, 1, 2, n_rows, n_rows + 1)
  235. size_widgets.append(spin)
  236. n_rows += 1
  237.  
  238. self._setup_position_widgets()
  239. self._setup_size_widgets()
  240. table.show_all()
  241.  
  242. def run(self):
  243. response = super(type(self), self).run()
  244. if response != gtk.RESPONSE_OK: return response
  245.  
  246. settings = self.exaile.settings
  247. plugin = self.plugin
  248. plugin_name = self.plugin_name
  249.  
  250. keep_center = not self.position_check.get_active()
  251. if plugin:
  252. plugin.set_keep_center(keep_center)
  253. settings.set_boolean('keep_center', keep_center, plugin=plugin_name)
  254.  
  255. gravity = self.gravity_combo.get_active()
  256. if plugin:
  257. plugin.set_gravity(GRAVITIES[gravity][1])
  258. settings.set_int('gravity', gravity, plugin=plugin_name)
  259.  
  260. use_image_size = not self.sizing_check.get_active()
  261. if plugin:
  262. plugin.set_use_image_size(use_image_size)
  263. settings.set_boolean('use_image_size', use_image_size,
  264. plugin=plugin_name)
  265.  
  266. width = self.width_spin.get_value_as_int()
  267. height = self.height_spin.get_value_as_int()
  268. if plugin:
  269. plugin.set_size(width, height)
  270. settings.set_int('width', width, plugin=plugin_name)
  271. settings.set_int('height', height, plugin=plugin_name)
  272.  
  273. x = self.x_spin.get_value_as_int()
  274. y = self.y_spin.get_value_as_int()
  275. if plugin:
  276. plugin.set_position(x, y)
  277. settings.set_int('x', x, plugin=plugin_name)
  278. settings.set_int('y', y, plugin=plugin_name)
  279.  
  280. return response
  281.  
  282. def _positioning_toggled(self, check, *data):
  283. self._setup_position_widgets(check.get_active())
  284.  
  285. def _sizing_toggled(self, check, *data):
  286. self._setup_size_widgets(check.get_active())
  287.  
  288. def _setup_position_widgets(self, enabled=None):
  289. if enabled is None:
  290. enabled = not self.exaile.settings.get_boolean('keep_center',
  291. default=True, plugin=self.plugin_name)
  292. for w in self.position_widgets:
  293. w.set_sensitive(enabled)
  294.  
  295. def _setup_size_widgets(self, enabled=None):
  296. if enabled is None:
  297. enabled = not self.exaile.settings.get_boolean('use_image_size',
  298. default=True, plugin=self.plugin_name)
  299. for w in self.size_widgets:
  300. w.set_sensitive(enabled)
  301.  
  302. def initialize():
  303. global PLUGIN
  304. PLUGIN = CoverDisplay()
  305.  
  306. settings = APP.settings
  307. plugin_name = plugins.name(__file__)
  308.  
  309. PLUGIN.set_keep_center(settings.get_boolean('keep_center', default=True,
  310. plugin=plugin_name))
  311. gravity = settings.get_int('gravity', default=0, plugin=plugin_name)
  312. PLUGIN.set_gravity(GRAVITIES[gravity][1])
  313. x = settings.get_int('x', default=PLUGIN.DEFAULT_X, plugin=plugin_name)
  314. y = settings.get_int('y', default=PLUGIN.DEFAULT_Y, plugin=plugin_name)
  315. PLUGIN.set_position(x, y)
  316. PLUGIN.set_use_image_size(settings.get_boolean('use_image_size',
  317. default=True, plugin=plugin_name))
  318. width = settings.get_int('width', default=PLUGIN.DEFAULT_WIDTH,
  319. plugin=plugin_name)
  320. height = settings.get_int('height', default=PLUGIN.DEFAULT_HEIGHT,
  321. plugin=plugin_name)
  322. PLUGIN.set_size(width, height)
  323.  
  324. player = APP.player
  325. if player.current and (player.is_playing() or player.is_paused()):
  326. _display(APP.cover.loc)
  327.  
  328. CONNS.connect(APP.cover, 'image-changed', lambda w, c: _display(c))
  329.  
  330. return True
  331.  
  332. def destroy():
  333. global PLUGIN
  334. CONNS.disconnect_all()
  335. PLUGIN.destroy()
  336. PLUGIN = None
  337.  
  338. def configure():
  339. dialog = DesktopCoverConfig(APP, PLUGIN_NAME, PLUGIN,
  340. plugins.name(__file__))
  341. dialog.run()
  342. dialog.destroy()
  343.  
  344. STOPPED = None
  345.  
  346. def _display(cover):
  347. global STOPPED
  348. if 'nocover' in cover:
  349. STOPPED = True
  350. # Wait to make sure playback is really stopped.
  351. gobject.timeout_add(200, _set_no_cover)
  352. else:
  353. STOPPED = False
  354. PLUGIN.display(cover)
  355.  
  356. def _set_no_cover():
  357. if STOPPED:
  358. PLUGIN.display(None)
  359. return False # Stop GLib timeout.
  360.  
  361. # vi: et sts=4 sw=4 tw=80
Add Comment
Please, Sign In to add comment