# -*- 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()