File: plugin.vala

package info (click to toggle)
libfsoframework 0.11.0-1.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,052 kB
  • sloc: sh: 11,311; ansic: 7,896; makefile: 89
file content (177 lines) | stat: -rw-r--r-- 4,972 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
 * Copyright (C) 2009-2011 Michael 'Mickey' Lauer <mlauer@vanille-media.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library 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
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 */

using GLib;

internal const string FSO_REGISTER_FUNCTION = "fso_register_function";
internal const string FSO_FACTORY_FUNCTION = "fso_factory_function";
internal const string FSO_SHUTDOWN_FUNCTION = "fso_shutdown_function";

/**
 * Errors
 */
public errordomain FsoFramework.PluginError
{
    UNABLE_TO_LOAD,
    REGISTER_NOT_FOUND,
    FACTORY_NOT_FOUND,
    UNABLE_TO_INITIALIZE,
}

/**
 * Delegates
 */
[CCode (has_target = false)]
public delegate void FsoFramework.RegisterFunc( TypeModule bar );
[CCode (has_target = false)]
public delegate string FsoFramework.FactoryFunc( FsoFramework.Subsystem subsystem ) throws Error;
[CCode (has_target = false)]
public delegate void FsoFramework.ShutdownFunc();

/**
 * PluginInfo
 */
public struct FsoFramework.PluginInfo
{
    public string name;
    public bool loaded;
}

/**
 * Plugin
 */
public abstract interface FsoFramework.Plugin : Object
{
    public abstract void loadAndInit() throws FsoFramework.PluginError;
    public abstract PluginInfo info();
    public abstract void shutdown();
}

/**
 * BasePlugin
 */
public class FsoFramework.BasePlugin : FsoFramework.Plugin, TypeModule
{
    string filename;
    Module module;
    FsoFramework.PluginInfo pluginInfo;
    FsoFramework.Subsystem subsystem;

    public BasePlugin( string filename, FsoFramework.Subsystem subsystem )
    {
        this.filename = "%s.%s".printf( filename, Module.SUFFIX );
        this.subsystem = subsystem;
        pluginInfo = FsoFramework.PluginInfo() { name=null, loaded=false };

        // FIXME: bump ref so it doesn't get disposed. This works around a bug in
        // Vala -- removing an unsolicitated call to g_object_dispose in TypeModule.
        this.ref();
    }

    public void loadAndInit() throws FsoFramework.PluginError
    {
        // try to load it
        module = Module.open( filename, ModuleFlags.BIND_LAZY | ModuleFlags.BIND_LOCAL );
        if ( module == null )
        {
            throw new FsoFramework.PluginError.UNABLE_TO_LOAD( @"Could not load $filename: $(Module.error())" );
        }

        // try to resolve register method
        void* regfunc;
        var ok = module.symbol( FSO_REGISTER_FUNCTION, out regfunc );

        if ( !ok )
        {
            throw new FsoFramework.PluginError.REGISTER_NOT_FOUND( @"Could not find symbol $FSO_REGISTER_FUNCTION: $(Module.error())" );
        }

        FsoFramework.RegisterFunc fso_register_function = (FsoFramework.RegisterFunc) regfunc;
        fso_register_function( this );

        // try to resolve factory method
        void* loadfunc;
        ok = module.symbol( FSO_FACTORY_FUNCTION, out loadfunc );
        if ( !ok )
        {
            throw new FsoFramework.PluginError.FACTORY_NOT_FOUND( @"Could not find symbol $FSO_FACTORY_FUNCTION: $(Module.error())" );
        }

        FactoryFunc fso_factory_func = (FactoryFunc) loadfunc;

        try
        {
            // call factory method to acquire name
            pluginInfo.name = fso_factory_func( subsystem );
            // flag as loaded
            pluginInfo.loaded = true;
        }
        catch ( Error e )
        {
            module = null;
            throw new FsoFramework.PluginError.UNABLE_TO_INITIALIZE( @"Factory function returned error: $(e.message)" );
        }
    }

    public PluginInfo info()
    {
        return pluginInfo;
    }

    public override bool load()
    {
#if DEBUG
        debug( @"$filename load (GType is in use)" );
#endif
        return true;
    }

    public override void unload()
    {
#if DEBUG
        debug( @"$filename unload (GType is no longer in use)" );
#endif
    }

    public void shutdown()
    {
        if ( module == null )
        {
            return;
        }
#if DEBUG
        message( @"$filename shutdown" );
#endif
        // try to resolve shutdown method
        void* func;
        var ok = module.symbol( FSO_SHUTDOWN_FUNCTION, out func );

        if ( !ok )
        {
            return;
        }

        FsoFramework.ShutdownFunc fso_shutdown_function = (FsoFramework.ShutdownFunc) func;
        fso_shutdown_function();
    }

}

// vim:ts=4:sw=4:expandtab