PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/history/__init__.py

https://bitbucket.org/synic/exaile
Python | 311 lines | 255 code | 25 blank | 31 comment | 5 complexity | d5f08768cdd3d392a853738805a0deca MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, BSD-2-Clause, BSD-3-Clause
  1. # Copyright (C) 2011 Dustin Spicuzza
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2, or (at your option)
  6. # any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. #
  18. # The developers of the Exaile media player hereby grant permission
  19. # for non-GPL compatible GStreamer and Exaile plugins to be used and
  20. # distributed together with GStreamer and Exaile. This permission is
  21. # above and beyond the permissions granted by the GPL license by which
  22. # Exaile is covered. If you modify this code, you may extend this
  23. # exception to your version of the code, but you are not obligated to
  24. # do so. If you do not wish to do so, delete this exception statement
  25. # from your version.
  26. import gtk
  27. import gobject
  28. import os
  29. import os.path
  30. import datetime
  31. from xl import (
  32. event,
  33. player,
  34. providers,
  35. settings,
  36. xdg
  37. )
  38. from xl.playlist import Playlist
  39. from xl.nls import gettext as _
  40. import xlgui
  41. from xlgui import main
  42. from xlgui.widgets import menu, dialogs
  43. from xlgui.widgets.notebook import NotebookPage, NotebookTab
  44. from xlgui.widgets.playlist import PlaylistView
  45. import history_preferences
  46. plugin = None
  47. def get_preferences_pane():
  48. return history_preferences
  49. def enable(exaile):
  50. '''Called on plugin enable'''
  51. if exaile.loading:
  52. event.add_callback(_enable, 'exaile_loaded')
  53. else:
  54. _enable(None, exaile, None)
  55. def _enable(eventname, exaile, nothing):
  56. global plugin
  57. plugin = HistoryPlugin(exaile)
  58. def disable(exaile):
  59. '''Called on plugin disable'''
  60. global plugin
  61. if plugin is not None:
  62. plugin.disable_plugin(exaile)
  63. plugin = None
  64. def teardown(exaile):
  65. '''Called on exaile quit'''
  66. global plugin
  67. if plugin is not None:
  68. plugin.teardown_plugin(exaile)
  69. class HistoryPlugin(object):
  70. '''Implements logic for plugin'''
  71. def __init__(self, exaile):
  72. self.exaile = exaile
  73. save_on_exit = settings.get_option('plugin/history/save_on_exit', history_preferences.save_on_exit_default)
  74. shown = settings.get_option('plugin/history/shown', False)
  75. # immutable playlist that stores everything we've played
  76. self.history_loc = os.path.join(xdg.get_data_dir(), 'history')
  77. self.history_playlist = HistoryPlaylist( player.PLAYER )
  78. if save_on_exit:
  79. self.history_playlist.load_from_location( self.history_loc )
  80. self.history_page = HistoryPlaylistPage( self.history_playlist, player.PLAYER )
  81. self.history_tab = NotebookTab(main.get_playlist_notebook(), self.history_page )
  82. # add menu item to 'view' to display our playlist
  83. self.menu = menu.check_menu_item( 'history', '', _('Playback history'), \
  84. lambda *e: self.is_shown(), self.on_playback_history )
  85. providers.register( 'menubar-view-menu', self.menu )
  86. # add the history playlist to the primary notebook
  87. if save_on_exit and shown:
  88. self.show_history( True )
  89. def teardown_plugin(self, exaile):
  90. '''Called when exaile is exiting'''
  91. if settings.get_option('plugin/history/save_on_exit', history_preferences.save_on_exit_default ):
  92. self.history_playlist.save_to_location( self.history_loc )
  93. settings.set_option( 'plugin/history/shown', self.is_shown() )
  94. else:
  95. settings.set_option( 'plugin/history/shown', False )
  96. self.show_history(False)
  97. def disable_plugin(self, exaile):
  98. '''Called when the plugin is disabled'''
  99. if self.menu:
  100. providers.unregister( 'menubar-view-menu', self.menu )
  101. self.menu = None
  102. self.show_history(False)
  103. if os.path.exists( self.history_loc ):
  104. dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
  105. _('Erase stored history?') )
  106. if dialog.run() == gtk.RESPONSE_YES:
  107. try:
  108. os.unlink( self.history_loc )
  109. except:
  110. pass
  111. dialog.destroy()
  112. def is_shown(self):
  113. return main.get_playlist_notebook().page_num( self.history_page ) != -1
  114. def on_playback_history(self, menu, name, parent, context):
  115. self.show_history( not self.is_shown() )
  116. def show_history(self, show):
  117. if show == self.is_shown():
  118. return
  119. if show:
  120. pn = main.get_playlist_notebook()
  121. pn.add_tab( self.history_tab, self.history_page )
  122. else:
  123. self.history_tab.close()
  124. class HistoryPlaylistPage( NotebookPage ):
  125. # add two buttons on the bottom: 'save to playlist', and
  126. # clear history. Use the dirty key to figure out if we
  127. # warn about clearing history..
  128. menu_provider_name = 'history-tab-context-menu'
  129. reorderable = False
  130. def __init__(self, playlist, player):
  131. NotebookPage.__init__(self)
  132. self.playlist = playlist
  133. self.swindow = gtk.ScrolledWindow()
  134. self.swindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  135. self.pack_start(self.swindow, True, True)
  136. self.view = PlaylistView(self.playlist, player)
  137. self.swindow.add(self.view)
  138. hbox = gtk.HButtonBox()
  139. button = gtk.Button(stock=gtk.STOCK_CLEAR)
  140. button.connect( 'clicked', self.on_clear_history )
  141. hbox.pack_start( button )
  142. button = gtk.Button(stock=gtk.STOCK_SAVE)
  143. button.connect( 'clicked', self.on_save_history )
  144. hbox.pack_start( button )
  145. align = gtk.Alignment( 1.0, 0.0 )
  146. align.add( hbox )
  147. self.pack_start( align, False, False )
  148. self.show_all()
  149. ## NotebookPage API ##
  150. def get_page_name(self):
  151. return _("History")
  152. ## End NotebookPage ##
  153. def on_clear_history( self, widget ):
  154. self.playlist._clear()
  155. def on_save_history( self, widget ):
  156. self.save_history()
  157. def save_history(self):
  158. if len(self.playlist) == 0:
  159. return
  160. name = 'History %s' % datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
  161. playlists = xlgui.get_controller().panels['playlists']
  162. playlists.add_new_playlist( self.playlist, name )
  163. def __create_history_tab_context_menu():
  164. smi = menu.simple_menu_item
  165. sep = menu.simple_separator
  166. items = []
  167. items.append(smi('save', [], _("Save History"), 'gtk-save',
  168. lambda w, n, o, c: o.save_history()))
  169. items.append(smi('clear', ['save'], _("Clear History"), 'gtk-clear',
  170. lambda w, n, o, c: o.playlist._clear()))
  171. items.append(sep('tab-close-sep', ['clear']))
  172. items.append(smi('tab-close', ['tab-close-sep'], None, 'gtk-close',
  173. lambda w, n, o, c: o.tab.close()))
  174. for item in items:
  175. providers.register( 'history-tab-context-menu', item )
  176. __create_history_tab_context_menu()
  177. class HistoryPlaylist( Playlist ):
  178. def __init__(self, player):
  179. Playlist.__init__( self, _('History') )
  180. # catch the history
  181. event.add_callback( self.__on_playback_track_start, 'playback_track_start', player )
  182. if player.is_paused() or player.is_playing():
  183. self.__on_playback_track_start( 'playback_track_start', player, player.current )
  184. def __on_playback_track_start(self, event, player, track):
  185. '''Every time a track plays, add it to the playlist'''
  186. maxlen = int(settings.get_option( 'plugin/history/history_length', history_preferences.history_length_default ))
  187. if maxlen < 0:
  188. maxlen = 0
  189. settings.set_option( 'plugin/history/history_length', 0 )
  190. if len(self) >= maxlen-1:
  191. Playlist.__delitem__( self, slice(0, max(0, len(self)-(maxlen-1)), None) )
  192. Playlist.__setitem__( self, slice(len(self),len(self),None), [track] )
  193. def _clear(self):
  194. Playlist.__delitem__( self, slice(None, None, None) )
  195. #
  196. # Suppress undesirable playlist functions, history playlist is immutable
  197. #
  198. def clear(self):
  199. pass
  200. def set_shuffle_mode(self, mode):
  201. pass
  202. def set_repeat_mode(self, mode):
  203. pass
  204. def set_dynamic_mode(self, mode):
  205. pass
  206. def randomize(self, positions=None):
  207. pass
  208. def sort(self, tags, reverse=False):
  209. pass
  210. def __setitem__(self, i, value):
  211. pass
  212. def __delitem__(self, i):
  213. pass
  214. def append(self, other):
  215. pass
  216. def extend(self, other):
  217. pass
  218. def pop(self, i=-1):
  219. pass