def loadAll():
    "Load all the plugins from the plugins directory."

    global initCommands
    initCommands = []

    # We'll only use the modified sys.path during this function.
    oldPath = sys.path

    # Make the plugins directory the one where to look first.
    sys.path = [PLUGIN_PATH] + sys.path

    found = []

    for fileName in paths.listFiles(paths.PLUGINS):
        if paths.hasExtension('py', fileName) or \
           (paths.hasExtension('plugin', fileName) and os.path.isdir(fileName)):
            if fileName not in found:
                found.append(fileName)
                
    # Sort alphabetically across all located plugins.
    found.sort(key=sortKey)
    for fileName in found:
        if paths.hasExtension('py', fileName):
            loadSingle(fileName) # Single Python module.
        elif paths.hasExtension('plugin', fileName):            
            loadBundle(fileName) # A plugin bundle.

    # Import all plugin modules.
    for importStatement, initStatement, searchPath in initCommands:
        sys.path = searchPath
        try:
            exec importStatement
        except:
            logger.add(logger.HIGH, 'error-plugin-init-failed', importStatement,
                       logger.formatTraceback())

    # Initialize all plugins.
    for importStatement, initStatement, searchPath in initCommands:
        sys.path = searchPath
        try:
            exec initStatement
        except AttributeError, ex:
            if "'init'" not in str(ex):
                logger.add(logger.HIGH, 'error-plugin-init-failed', initStatement,
                           logger.formatTraceback())
        except:
def send(event):
    """Broadcast an event to all listeners of the appropriate type.
    The event is processed synchronously: all listeners will be
    notified immediately during the execution of this function.

    @param event The event to send.  All listeners will get the same
    event object.
    """
    if areEventsMuted:
        return # Discard.

    global sendDepth, queuedEvents

    sendDepth += 1
    
    # Commands and Notifys go to a different set of listeners.
    if event.myClass == Command:
        listeners = commandListeners
    else:
        listeners = notifyListeners

    # The identifier of the event to be sent.
    sendId = event.getId()
    
    # Always include the unfiltered callbacks.
    callbacks = [c for c in listeners[None]]
    
    if listeners.has_key(sendId):
        # The specialized callbacks.
        callbacks += listeners[sendId]

    #print "Sending " + sendId + ":"
    #print callbacks

    # Send the event to all the appropriate listeners.
    for callback in callbacks:
        try:
            callback(event)
        except Exception, x:
			# Report errors.
            import logger
            logger.add(logger.HIGH, 'error-runtime-exception-during-event',
					   sendId, str(x), logger.formatTraceback())
            logger.show()
            logger.add(logger.HIGH, 'error-plugin-init-failed', importStatement,
                       logger.formatTraceback())

    # Initialize all plugins.
    for importStatement, initStatement, searchPath in initCommands:
        sys.path = searchPath
        try:
            exec initStatement
        except AttributeError, ex:
            if "'init'" not in str(ex):
                logger.add(logger.HIGH, 'error-plugin-init-failed', initStatement,
                           logger.formatTraceback())
        except:
            # Any problems during init cause the plugin to be ignored.
            logger.add(logger.HIGH, 'error-plugin-init-failed', initStatement,
                       logger.formatTraceback())
    
    sys.path = oldPath


def loadSingle(fileName, package=None):
    """Load a plugin that consists of a single .py module in a plugins
    directory.

    @param fileName File name of the the plugin.
    """
    name = paths.getBase(fileName)

    obsoletePluginNames = ['tab1_summary', 'tab2_addons', 'tab3_settings', 'tab30_addons']
    
    # Old plugin names.