# -*- coding: utf-8 -*- # Bluemindo # __init__.py # Bluemindo: A really simple but powerful audio player in Python/PyGTK. # Copyright (C) 2007-2008 Erwan Briand # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation version 3 of the License. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . from gettext import gettext as _ from gtk import (ListStore, CellRendererText, TreeViewColumn, CellRendererPixbuf, ICON_SIZE_LARGE_TOOLBAR, WIN_POS_CENTER_ALWAYS) from gtk.glade import XML as glade_XML from gtk.gdk import Pixbuf as gPixbuf, pixbuf_new_from_file from gobject import TYPE_STRING as gString from os.path import join, isdir, isfile, realpath from os import listdir, getcwd from gui.aboutdialog import AboutDialog from common.functions import Functions functions = Functions() class ExtensionsLoader: def __init__(self): # All available signals # If you think you need another signal, please report a bug. self.signals = { 'OnBluemindoStarted': list(), # When Bluemindo is starting # glade 'OnBluemindoWindowClosed': list(), # When Bluemindo main window is closed 'OnBluemindoQuitted': list(), # When Bluemindo is quitted 'OnMenuRefreshPressed': list(), # When database refresh is requested # glade 'OnToolLyricsPressed': list(), # When lyrics button is pressed 'OnToolReloadLyricsPressed': list(), # When lyrics reload button is pressed 'OnToolSaveLyricsPressed': list(), # When lyrics save button is pressed 'OnModuleConfiguration': list(), # When a module is waiting for configuration # (module, confglade) 'OnModuleConfigurationSave': list(), # When: Exit from module's configuration # module 'OnStatusIconAnswer': list(), # We send the gtk.StatusIcon # status_icon_id 'OnPlaylistRequested': list(), # When we open a playlist # playlist_name 'OnPreviousPressed': list(), # When previous button is pressed 'OnStopPressed': list(), # When stop button is pressed 'OnPlayPressed': list(), # When play button is pressed 'OnNextPressed': list(), # When next button is pressed 'OnPlayPressedWithoutQueue': list(), # When play is pressed with an empty playlist 'OnPlayNewSong': list() # When a new song have to be launched # (track, title, artist, album, genre, length, filename, reallength) } # Starting self.modules = [] self.plugins = [] self.conflist = {} self.is_in_config = False # Load modules and plugins self.load() def load(self): """Load all modules and plugins""" # Load both modules and plugins for exttype in ('modules', 'plugins'): for file_ in listdir(exttype): # Get only modules without `.` as first # character (exclude .svn/) if (isdir(join(getcwd(), exttype, file_)) and not file_.startswith('.')): name = file_.lower() # Try to load the module try: module = __import__(''.join([exttype + '.', name])) cls = getattr(getattr(module, name), name.capitalize()) obj = cls(self) if exttype == 'modules': self.modules.append(obj.module) elif exttype == 'plugins': self.plugins.append(obj.plugin) except Exception, error: print ('Extension `%s`, registered in *%s*, could not ' 'start.' % (file_, exttype) ) print error print '---------' print '' if exttype == 'modules': raise SystemExit("Bluemindo's modules are required " "to launch the software.\n" "Exiting.") def connect(self, signal, function): """Connect a signal with a module's function""" if self.signals.has_key(signal): self.signals[signal].append(function) else: print '`%s` don\'t exist.' % signal def load_event(self, signal, *args): """Load an event, call related functions""" if self.signals.has_key(signal): dct = self.signals[signal] for dct_ in dct: if len(args) == 1: dct_(args[0]) elif len(args) > 1: dct_(args) else: dct_() else: print '`%s` don\'t exist.' % signal def configure(self): """Create the configuration GUI""" self.widgets = glade_XML(functions.datadir + '/glade/prefswindow.glade', 'window1', domain='bluemindo') window = self.widgets.get_widget('window1') window.set_position(WIN_POS_CENTER_ALWAYS) window.set_title(_('Preferences')) window.connect('delete_event', self.on_window_close) self.widgets.get_widget('button-validate').connect( 'clicked', self.close, window) # About self.widgets.get_widget('button1').connect('clicked', self.about) # Load both modules and plugins for exttype in ('modules', 'plugins'): liststore = ListStore(gPixbuf, gString, gString) if exttype == 'modules': treeview = self.widgets.get_widget('treeview1') elif exttype == 'plugins': treeview = self.widgets.get_widget('treeview2') treeview.set_model(liststore) column = TreeViewColumn() render_pixbuf = CellRendererPixbuf() column.pack_start(render_pixbuf, expand=False) column.add_attribute(render_pixbuf, 'pixbuf', 0) render_text = CellRendererText() column.pack_start(render_text, expand=True) column.add_attribute(render_text, 'markup', 1) treeview.append_column(column) treeview.set_rules_hint(True) treeview.get_selection().connect('changed', self.openconf) if exttype == 'modules': extensions = self.modules elif exttype == 'plugins': extensions = self.plugins extensions.sort(lambda x, y : cmp(x['name'], y['name'])) for extension in extensions: if extension['configurable']: if isfile(extension['logo']): icon = pixbuf_new_from_file(extension['logo']) else: icon = treeview.render_icon(stock_id=extension['logo'], size=ICON_SIZE_LARGE_TOOLBAR, detail=None) title = '%s' % extension['name'] self.conflist[title] = extension liststore.append((icon, title, extensions)) def on_window_close(self, widget, event): """Save configuration on window close""" # Configure current extension if self.is_in_config: self.load_event('OnModuleConfigurationSave', self.is_in_config) self.is_in_config = False def close(self, widget, window): """Save configuration on button click""" # Configure current extension if self.is_in_config: self.load_event('OnModuleConfigurationSave', self.is_in_config) self.is_in_config = False window.destroy() def openconf(self, selection): """Open configuration""" # Configure current extension if self.is_in_config: self.load_event('OnModuleConfigurationSave', self.is_in_config) self.is_in_config = False # Load a new configuration if selection: (mod, iter_) = selection.get_selected() if iter_: name = mod.get_value(iter_, 1) extension = self.conflist[name]['name'] self.is_in_config = self.conflist[name]['name'] self.load_event('OnModuleConfiguration', (extension, self.widgets)) def about(self, widget): """Show an AboutDialog for the selected extension""" notepad = self.widgets.get_widget('notebook1') current = notepad.get_current_page() # If the extension is a module, show the Bluemindo's AboutDialog # instead of a specialized one if current == 0: AboutDialog() # Ensure it's a plugin :-) elif current == 1: treeview = self.widgets.get_widget('treeview2') (mod, iter_) = treeview.get_selection().get_selected() if iter_: # Get plugin's informations _name_ = mod.get_value(iter_, 1) name = self.conflist[_name_]['name'] version = self.conflist[_name_]['version'] logo = self.conflist[_name_]['logo'] description = self.conflist[_name_]['description'] license = self.conflist[_name_]['license'] authors = self.conflist[_name_]['authors'] if isfile(logo): logopixbuf = pixbuf_new_from_file(logo) else: logopixbuf = None # Construct the AboutDialog about_widgets = glade_XML( functions.datadir + '/glade/prefswindow.glade', 'aboutdialog1', domain='bluemindo') about_dialog = about_widgets.get_widget('aboutdialog1') # Add datas about_dialog.set_name(name) about_dialog.set_version(str(version)) about_dialog.set_comments(description) about_dialog.set_logo(logopixbuf) if license == 'GNU General Public License 3': gpl = open(functions.datadir + '/COPYING', 'r') about_dialog.set_license(gpl.read()) gpl.close() about_dialog.set_copyright(authors) else: about_dialog.set_copyright(authors + '\n' + license) # Show the AboutDialog and exit about_dialog.run() about_dialog.destroy()