CoverArt Browser  v2.0
Browse your cover-art albums in Rhythmbox
/home/foss/Downloads/coverart-browser/coverart_browser.py
00001 # -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
00002 #
00003 # Copyright (C) 2012 - fossfreedom
00004 # Copyright (C) 2012 - Agustin Carrasco
00005 #
00006 # This program is free software; you can redistribute it and/or modify
00007 # it under the terms of the GNU General Public License as published by
00008 # the Free Software Foundation; either version 2, or (at your option)
00009 # any later version.
00010 #
00011 # This program is distributed in the hope that it will be useful,
00012 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 # GNU General Public License for more details.
00015 #
00016 # You should have received a copy of the GNU General Public License
00017 # along with this program; if not, write to the Free Software
00018 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
00019 
00020 # define plugin
00021 from gi.repository import GObject
00022 from gi.repository import Gtk
00023 from gi.repository import RB
00024 from gi.repository import Peas
00025 from gi.repository import Gio
00026 from gi.repository import GLib
00027 
00028 import rb
00029 from coverart_browser_prefs import GSetting
00030 from coverart_browser_prefs import CoverLocale
00031 from coverart_browser_prefs import Preferences
00032 from coverart_browser_source import CoverArtBrowserSource
00033 from coverart_listview import ListView
00034 from coverart_queueview import QueueView
00035 from coverart_playsourceview import PlaySourceView
00036 from coverart_toolbar import TopToolbar
00037 
00038 class CoverArtBrowserEntryType(RB.RhythmDBEntryType):
00039     '''
00040     Entry type for our source.
00041     '''
00042 
00043     def __init__(self):
00044         '''
00045         Initializes the entry type.
00046         '''
00047         RB.RhythmDBEntryType.__init__(self, name='CoverArtBrowserEntryType')
00048 
00049 class CoverArtBrowserPlugin(GObject.Object, Peas.Activatable):
00050     '''
00051     Main class of the plugin. Manages the activation and deactivation of the
00052     plugin.
00053     '''
00054     __gtype_name = 'CoverArtBrowserPlugin'
00055     object = GObject.property(type=GObject.Object)
00056 
00057     def __init__(self):
00058         '''
00059         Initialises the plugin object.
00060         '''
00061         GObject.Object.__init__(self)
00062 
00063     def do_activate(self):
00064         '''
00065         Called by Rhythmbox when the plugin is activated. It creates the
00066         plugin's source and connects signals to manage the plugin's
00067         preferences.
00068         '''
00069 
00070         print("CoverArtBrowser DEBUG - do_activate")
00071         self.shell = self.object
00072         self.db = self.shell.props.db
00073 
00074         self.entry_type = CoverArtBrowserEntryType()
00075         self.db.register_entry_type(self.entry_type)
00076 
00077         cl = CoverLocale()
00078         cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
00079 
00080         self.entry_type.category = RB.RhythmDBEntryCategory.NORMAL
00081 
00082         group = RB.DisplayPageGroup.get_by_id('library')
00083 
00084         # load plugin icon
00085         theme = Gtk.IconTheme.get_default()
00086         rb.append_plugin_source_path(theme, '/icons')
00087 
00088         iconfile = Gio.File.new_for_path(
00089             rb.find_plugin_file(self, 'img/covermgr_rb3.png'))
00090 
00091         self.source = CoverArtBrowserSource(
00092             shell=self.shell,
00093             name=_("CoverArt"),
00094             entry_type=self.entry_type,
00095             plugin=self,
00096             icon=Gio.FileIcon.new(iconfile),
00097             query_model=self.shell.props.library_source.props.base_query_model)
00098 
00099         self.shell.register_entry_type_for_source(self.source, self.entry_type)
00100         self.shell.append_display_page(self.source, group)
00101 
00102         self.source.props.query_model.connect('complete', self.load_complete)
00103         self._externalmenu = ExternalPluginMenu(self)
00104 
00105         cl.switch_locale(cl.Locale.RB)
00106         print("CoverArtBrowser DEBUG - end do_activate")
00107 
00108     def do_deactivate(self):
00109         '''
00110         Called by Rhythmbox when the plugin is deactivated. It makes sure to
00111         free all the resources used by the plugin.
00112         '''
00113         print("CoverArtBrowser DEBUG - do_deactivate")
00114         self.source.delete_thyself()
00115         if self._externalmenu:
00116             self._externalmenu.cleanup()
00117         del self.shell
00118         del self.db
00119         del self.source
00120 
00121         print("CoverArtBrowser DEBUG - end do_deactivate")
00122 
00123     def load_complete(self, *args, **kwargs):
00124         '''
00125         Called by Rhythmbox when it has completed loading all data
00126         Used to automatically switch to the browser if the user
00127         has set in the preferences
00128         '''
00129         gs = GSetting()
00130         setting = gs.get_setting(gs.Path.PLUGIN)
00131 
00132         if setting[gs.PluginKey.AUTOSTART]:
00133             GLib.idle_add(self.shell.props.display_page_tree.select,
00134                           self.source)
00135 
00136     def _translation_helper(self):
00137         '''
00138         a method just to help out with translation strings
00139         it is not meant to be called by itself
00140         '''
00141 
00142         # define .plugin text strings used for translation
00143         plugin = _('CoverArt Browser')
00144         desc = _('Browse and play your albums through their covers')
00145 
00146         #. TRANSLATORS: This is the icon-grid view that the user sees
00147         tile = _('Tiles')
00148 
00149         #. TRANSLATORS: This is the cover-flow view the user sees - they can swipe album covers from side-to-side
00150         artist = _('Flow')
00151 
00152         #. TRANSLATORS: percentage size that the image will be expanded
00153         scale = _('Scale by %:')
00154 
00155         # stop PyCharm removing the Preference import on optimisation
00156         pref = Preferences()
00157 
00158 
00159 class ExternalPluginMenu(GObject.Object):
00160     toolbar_pos = GObject.property(type=str, default=TopToolbar.name)
00161 
00162     def __init__(self, plugin):
00163         super(ExternalPluginMenu, self).__init__()
00164 
00165         self.plugin = plugin
00166         self.shell = plugin.shell
00167         self.source = plugin.source
00168         self.app_id = None
00169         from coverart_browser_source import Views
00170 
00171         self._views = Views(self.shell)
00172 
00173         self._connect_properties()
00174         self._connect_signals()
00175 
00176         self._create_menu()
00177 
00178     def _connect_signals(self):
00179         self.connect('notify::toolbar-pos', self._on_notify_toolbar_pos)
00180         self.shell.props.display_page_tree.connect(
00181             "selected", self.on_page_change
00182         )
00183 
00184     def _connect_properties(self):
00185         gs = GSetting()
00186         setting = gs.get_setting(gs.Path.PLUGIN)
00187         setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
00188                      Gio.SettingsBindFlags.GET)
00189 
00190     def _on_notify_toolbar_pos(self, *args):
00191         if self.toolbar_pos == TopToolbar.name:
00192             self._create_menu()
00193         else:
00194             self.cleanup()
00195 
00196     def cleanup(self):
00197         if self.app_id:
00198             app = Gio.Application.get_default()
00199             for location in self.locations:
00200                 app.remove_plugin_menu_item(location, self.app_id)
00201             self.app_id = None
00202 
00203     def _create_menu(self):
00204         app = Gio.Application.get_default()
00205         self.app_id = 'coverart-browser'
00206 
00207         self.locations = ['library-toolbar', 'queue-toolbar', 'playsource-toolbar']
00208         action_name = 'coverart-browser-views'
00209         self.action = Gio.SimpleAction.new_stateful(
00210             action_name, GLib.VariantType.new('s'),
00211             self._views.get_action_name(ListView.name)
00212         )
00213         self.action.connect("activate", self.view_change_cb)
00214         app.add_action(self.action)
00215 
00216         menu_item = Gio.MenuItem()
00217         section = Gio.Menu()
00218         menu = Gio.Menu()
00219         toolbar_item = Gio.MenuItem()
00220 
00221         for view_name in self._views.get_view_names():
00222             menu_item.set_label(self._views.get_menu_name(view_name))
00223             menu_item.set_action_and_target_value(
00224                 'app.' + action_name, self._views.get_action_name(view_name)
00225             )
00226             section.append_item(menu_item)
00227 
00228         menu.append_section(None, section)
00229 
00230         cl = CoverLocale()
00231         cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
00232         toolbar_item.set_label(_('Views'))
00233         cl.switch_locale(cl.Locale.RB)
00234 
00235         toolbar_item.set_submenu(menu)
00236         for location in self.locations:
00237             app.add_plugin_menu_item(location, self.app_id, toolbar_item)
00238 
00239 
00240     def on_page_change(self, display_page_tree, page):
00241         '''
00242         Called when the display page changes. Grabs query models and sets the 
00243         active view.
00244         '''
00245 
00246         if page == self.shell.props.library_source:
00247             self.action.set_state(self._views.get_action_name(ListView.name))
00248         elif page == self.shell.props.queue_source:
00249             self.action.set_state(self._views.get_action_name(QueueView.name))
00250         #elif page == self.source.playlist_source:
00251         #    self.action.set_state(self._views.get_action_name(PlaySourceView.name))
00252 
00253 
00254     def view_change_cb(self, action, current):
00255         '''
00256         Called when the view state on a page is changed. Sets the new 
00257         state.
00258         '''
00259         action.set_state(current)
00260         view_name = self._views.get_view_name_for_action(current)
00261         if view_name != ListView.name and \
00262            view_name != QueueView.name:# and \
00263             #view_name != PlaySourceView.name:
00264             gs = GSetting()
00265             setting = gs.get_setting(gs.Path.PLUGIN)
00266             setting[gs.PluginKey.VIEW_NAME] = view_name
00267             GLib.idle_add(self.shell.props.display_page_tree.select,
00268                           self.source)
00269         elif view_name == ListView.name:
00270             GLib.idle_add(self.shell.props.display_page_tree.select,
00271                           self.shell.props.library_source)
00272         elif view_name == QueueView.name:
00273             GLib.idle_add(self.shell.props.display_page_tree.select,
00274                           self.shell.props.queue_source)
00275         #elif view_name == PlaySourceView.name:
00276         #    if not hasattr(self.source, 'playlist_source'):
00277         #        return
00278 
00279         #    print ("test selectable")
00280         #    path = self.shell.props.display_page_tree.props.model
00281         #        #self.source.activate()
00282         #    overlay = self.source.get_children()[0]
00283 
00284         #   GLib.idle_add(self.shell.props.display_page_tree.select,
00285         #                  self.source.playlist_source)
 All Classes Functions