{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, RankNTypes #-} ----------------------------------------------------------------------------- -- -- Module : Base.Plugin -- Copyright : Juergen "jutaro" Nicklisch-Franken -- License : GPL Nothing -- -- Maintainer : maintainer@leksah.org -- Stability : -- Portability : -- -- | Simple plugin system -- -- ----------------------------------------------------------------------------- module Base.Plugin ( Plugin(..), VersionBounds, Prerequisite, PluginName, PluginInterface(..), PluginConfig(..), BaseEvent, BaseEventValue(..), runAll, triggerBaseEvent, getBaseEvent ) where import Base import Data.Version (showVersion, Version(..)) import Data.IORef (writeIORef, readIORef, newIORef) import qualified Data.Map as Map (insert, empty, lookup) import Control.Monad.IO.Class (MonadIO(..)) import Data.Unique (newUnique) import System.Plugins (loadPackageFunction, load) import System.Plugins.Load (LoadStatus(..)) import Control.Monad (foldM, when) import Data.Maybe (catMaybes) import Data.Map (Map) import Data.Typeable (Typeable) -- | This has to be called from main runAll :: FilePath -> PluginConfig -> [Plugin] -> BaseEvent -> StateM () runAll pluginPath config loadList baseEvent = do message Debug ("runAll: " ++ show (map getPluginName loadList)) -- load and pre-init the plugins iniRes <- loadPlugins baseEvent loadList -- post-init the plugins mapM_ (\(GenInterface interface) -> initInterface baseEvent interface) (catMaybes iniRes) -- trigger the startup event (evtTrigger baseEvent) StartUp -- Here the application shall take control return () type Error = String initInterface :: BaseEvent -> PluginInterface event -> StateM() initInterface baseEvent interface = (piInit2 interface) baseEvent (piEvent interface) -- | Return type for the loading of plugins -- If the load fails, Nothing is returned -- | Load all the plugins, loadPlugins :: BaseEvent -> [Plugin] -> StateM [Maybe GenInterface] loadPlugins baseEvent loadList = mapM (loadPlugin baseEvent) loadList -- | Load one Plugin and call init1 loadPlugin :: BaseEvent -> Plugin -> StateM (Maybe GenInterface) loadPlugin baseEvent plug@Plugin{plInterface =funcName,plModule = moduleName} = do message Info ("loadPlugin " ++ getPluginName plug) mv <- liftIO $ loadPackageFunction (getPluginName plug) moduleName funcName -- TODO checkVersion case mv of Nothing -> message Error ("Cant load " ++ show (getPluginName plug)) >> return Nothing (Just interface) -> do message Info ("load succeeded " ++ getPluginName plug) (piInit1 interface) baseEvent (piEvent interface) return (Just (GenInterface interface)) type Warning = String