core/systems/PluginSys.cpp
author David Anderson <dvander@alliedmods.net>
Sat Nov 11 01:19:46 2006 +0000 (2006-11-11)
changeset 174 5611e4b3fa42
parent 173 662fc7f7144b
child 176 c1699993453c
permissions -rw-r--r--
initial import of proposed forward API
dvander@173
     1
#include <stdio.h>
dvander@173
     2
#include "PluginSys.h"
dvander@173
     3
dvander@174
     4
CPluginManager g_PluginMngr;
dvander@174
     5
dvander@174
     6
CPluginManager::CPluginManager()
dvander@174
     7
{
dvander@174
     8
}
dvander@173
     9
dvander@173
    10
CPlugin *CPlugin::CreatePlugin(const char *file, 
dvander@173
    11
								bool debug_default, 
dvander@174
    12
								PluginType type, 
dvander@173
    13
								char *error, 
dvander@173
    14
								size_t maxlen)
dvander@173
    15
{
dvander@173
    16
	static unsigned int MySerial = 0;
dvander@173
    17
	FILE *fp = fopen(file, "rb");
dvander@173
    18
dvander@173
    19
	if (!fp)
dvander@173
    20
	{
dvander@173
    21
		snprintf(error, maxlen, "Could not open file");
dvander@173
    22
		return NULL;
dvander@173
    23
	}
dvander@173
    24
dvander@173
    25
	int err;
dvander@173
    26
	sp_plugin_t *pl = g_pSourcePawn->LoadFromFilePointer(fp, &err);
dvander@173
    27
	if (pl == NULL)
dvander@173
    28
	{
dvander@173
    29
		snprintf(error, maxlen, "Could not load plugin, error %d", err);
dvander@173
    30
		return NULL;
dvander@173
    31
	}
dvander@173
    32
dvander@173
    33
	fclose(fp);
dvander@173
    34
dvander@173
    35
	ICompilation *co = g_pVM->StartCompilation(pl);
dvander@173
    36
	
dvander@173
    37
	if (debug_default)
dvander@173
    38
	{
dvander@173
    39
		if (!g_pVM->SetCompilationOption(co, "debug", "1"))
dvander@173
    40
		{
dvander@173
    41
			g_pVM->AbortCompilation(co);
dvander@173
    42
			snprintf(error, maxlen, "Could not set plugin to debug mode");
dvander@173
    43
			return NULL;
dvander@173
    44
		}
dvander@173
    45
	}
dvander@173
    46
dvander@173
    47
	sp_context_t *ctx = g_pVM->CompileToContext(co, &err);
dvander@173
    48
	if (ctx == NULL)
dvander@173
    49
	{
dvander@173
    50
		snprintf(error, maxlen, "Plugin failed to load, JIT error: %d", err);
dvander@173
    51
		return NULL;
dvander@173
    52
	}
dvander@173
    53
dvander@173
    54
	IPluginContext *base = g_pSourcePawn->CreateBaseContext(ctx);
dvander@173
    55
	CPlugin *pPlugin = new CPlugin;
dvander@173
    56
dvander@173
    57
	snprintf(pPlugin->m_filename, PLATFORM_MAX_PATH, "%s", file);
dvander@173
    58
	pPlugin->m_debugging = debug_default;
dvander@173
    59
	pPlugin->m_ctx_current.base = base;
dvander@173
    60
	pPlugin->m_ctx_current.ctx = ctx;
dvander@174
    61
	pPlugin->m_type = type;
dvander@173
    62
	pPlugin->m_serial = ++MySerial;
dvander@173
    63
	pPlugin->m_status = Plugin_Loaded;
dvander@173
    64
	pPlugin->m_plugin = pl;
dvander@173
    65
dvander@173
    66
	pPlugin->UpdateInfo();
dvander@173
    67
dvander@174
    68
	ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)(IPlugin *)pPlugin;
dvander@174
    69
dvander@173
    70
	return pPlugin;
dvander@173
    71
}
dvander@173
    72
dvander@173
    73
void CPlugin::UpdateInfo()
dvander@173
    74
{
dvander@173
    75
	/* Now grab the info */
dvander@173
    76
	uint32_t idx;
dvander@173
    77
	IPluginContext *base = GetBaseContext();
dvander@173
    78
	int err = base->FindPubvarByName("myinfo", &idx);
dvander@173
    79
dvander@173
    80
	if (err == SP_ERROR_NONE)
dvander@173
    81
	{
dvander@173
    82
		struct sm_plugininfo_c_t
dvander@173
    83
		{
dvander@173
    84
			cell_t name;
dvander@173
    85
			cell_t description;
dvander@173
    86
			cell_t author;
dvander@173
    87
			cell_t version;
dvander@173
    88
			cell_t url;
dvander@173
    89
		};
dvander@173
    90
		sm_plugininfo_c_t *cinfo;
dvander@173
    91
		cell_t local_addr;
dvander@173
    92
dvander@173
    93
		base->GetPubvarAddrs(idx, &local_addr, (cell_t **)&cinfo);
dvander@173
    94
		base->LocalToString(cinfo->name, (char **)&m_info.name);
dvander@173
    95
		base->LocalToString(cinfo->description, (char **)&m_info.description);
dvander@173
    96
		base->LocalToString(cinfo->author, (char **)&m_info.author);
dvander@173
    97
		base->LocalToString(cinfo->url, (char **)&m_info.url);
dvander@173
    98
		base->LocalToString(cinfo->version, (char **)&m_info.version);
dvander@173
    99
	}
dvander@173
   100
dvander@173
   101
	m_info.author = m_info.author ? m_info.author : "";
dvander@173
   102
	m_info.description = m_info.description ? m_info.description : "";
dvander@173
   103
	m_info.name = m_info.name ? m_info.name : "";
dvander@173
   104
	m_info.url = m_info.url ? m_info.url : "";
dvander@173
   105
	m_info.version = m_info.version ? m_info.version : "";
dvander@173
   106
}
dvander@173
   107
dvander@173
   108
const sp_plugin_t *CPlugin::GetPluginStructure() const
dvander@173
   109
{
dvander@173
   110
	return m_plugin;
dvander@173
   111
}
dvander@173
   112
dvander@173
   113
IPluginContext *CPlugin::GetBaseContext() const
dvander@173
   114
{
dvander@173
   115
	return m_ctx_current.base;
dvander@173
   116
}
dvander@173
   117
dvander@173
   118
sp_context_t *CPlugin::GetContext() const
dvander@173
   119
{
dvander@173
   120
	return m_ctx_current.ctx;
dvander@173
   121
}
dvander@173
   122
dvander@173
   123
const char *CPlugin::GetFilename() const
dvander@173
   124
{
dvander@173
   125
	return m_filename;
dvander@173
   126
}
dvander@173
   127
dvander@174
   128
PluginType CPlugin::GetType() const
dvander@173
   129
{
dvander@174
   130
	return m_type;
dvander@173
   131
}
dvander@173
   132
dvander@173
   133
const sm_plugininfo_t *CPlugin::GetPublicInfo() const
dvander@173
   134
{
dvander@173
   135
	return &m_info;
dvander@173
   136
}
dvander@173
   137
dvander@173
   138
unsigned int CPlugin::GetSerial() const
dvander@173
   139
{
dvander@173
   140
	return m_serial;
dvander@173
   141
}
dvander@173
   142
dvander@173
   143
PluginStatus CPlugin::GetStatus() const
dvander@173
   144
{
dvander@173
   145
	return m_status;
dvander@173
   146
}
dvander@173
   147
dvander@173
   148
bool CPlugin::IsDebugging() const
dvander@173
   149
{
dvander@173
   150
	return m_debugging;
dvander@173
   151
}
dvander@173
   152
dvander@173
   153
bool CPlugin::SetPauseState(bool paused)
dvander@173
   154
{
dvander@173
   155
	if (paused && GetStatus() != Plugin_Paused)
dvander@173
   156
	{
dvander@173
   157
		return false;
dvander@173
   158
	} else if (!paused && GetStatus() != Plugin_Running) {
dvander@173
   159
		return false;
dvander@173
   160
	}
dvander@173
   161
	
dvander@173
   162
	/* :TODO: execute some forwards or some crap */
dvander@173
   163
dvander@173
   164
	return true;
dvander@173
   165
}
dvander@174
   166
dvander@174
   167
/*******************
dvander@174
   168
 * PLUGIN ITERATOR *
dvander@174
   169
 *******************/
dvander@174
   170
CPluginManager::CPluginIterator::CPluginIterator(List<IPlugin *> *_mylist)
dvander@174
   171
{
dvander@174
   172
	mylist = _mylist;
dvander@174
   173
}
dvander@174
   174
dvander@174
   175
IPlugin *CPluginManager::CPluginIterator::GetPlugin()
dvander@174
   176
{
dvander@174
   177
	return (*current);
dvander@174
   178
}
dvander@174
   179
dvander@174
   180
bool CPluginManager::CPluginIterator::MorePlugins()
dvander@174
   181
{
dvander@174
   182
	return (current != mylist->end());
dvander@174
   183
}
dvander@174
   184
dvander@174
   185
void CPluginManager::CPluginIterator::NextPlugin()
dvander@174
   186
{
dvander@174
   187
	current++;
dvander@174
   188
}
dvander@174
   189
dvander@174
   190
void CPluginManager::CPluginIterator::Release()
dvander@174
   191
{
dvander@174
   192
	g_PluginMngr.ReleaseIterator(this);
dvander@174
   193
}
dvander@174
   194
dvander@174
   195
CPluginManager::CPluginIterator::~CPluginIterator()
dvander@174
   196
{
dvander@174
   197
}
dvander@174
   198
dvander@174
   199
void CPluginManager::CPluginIterator::Reset()
dvander@174
   200
{
dvander@174
   201
	current = mylist->begin();
dvander@174
   202
}
dvander@174
   203
dvander@174
   204
/******************
dvander@174
   205
 * PLUGIN MANAGER *
dvander@174
   206
 ******************/
dvander@174
   207
dvander@174
   208
IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t err_max)
dvander@174
   209
{
dvander@174
   210
	CPlugin *pPlugin = CPlugin::CreatePlugin(path, debug, type, error, err_max);
dvander@174
   211
dvander@174
   212
	if (!pPlugin)
dvander@174
   213
	{
dvander@174
   214
		return NULL;
dvander@174
   215
	}
dvander@174
   216
dvander@174
   217
	m_plugins.push_back(pPlugin);
dvander@174
   218
dvander@174
   219
	List<IPluginsListener *>::iterator iter;
dvander@174
   220
	IPluginsListener *pListener;
dvander@174
   221
	for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
dvander@174
   222
	{
dvander@174
   223
		pListener = (*iter);
dvander@174
   224
		pListener->OnPluginCreated(pPlugin);
dvander@174
   225
	}
dvander@174
   226
dvander@174
   227
	/* :TODO: a lot more... */
dvander@174
   228
dvander@174
   229
	return pPlugin;
dvander@174
   230
}
dvander@174
   231
dvander@174
   232
bool CPluginManager::UnloadPlugin(IPlugin *plugin)
dvander@174
   233
{
dvander@174
   234
	CPlugin *pPlugin = (CPlugin *)plugin;
dvander@174
   235
dvander@174
   236
	/* :TODO: More */
dvander@174
   237
dvander@174
   238
	List<IPluginsListener *>::iterator iter;
dvander@174
   239
	IPluginsListener *pListener;
dvander@174
   240
	for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
dvander@174
   241
	{
dvander@174
   242
		pListener = (*iter);
dvander@174
   243
		pListener->OnPluginDestroyed(pPlugin);
dvander@174
   244
	}
dvander@174
   245
dvander@174
   246
	if (pPlugin->m_ctx_current.base)
dvander@174
   247
	{
dvander@174
   248
		g_pSourcePawn->FreeBaseContext(pPlugin->m_ctx_current.base);
dvander@174
   249
	}
dvander@174
   250
	if (pPlugin->m_ctx_backup.base)
dvander@174
   251
	{
dvander@174
   252
		g_pSourcePawn->FreeBaseContext(pPlugin->m_ctx_backup.base);
dvander@174
   253
	}
dvander@174
   254
	if (pPlugin->m_ctx_current.ctx)
dvander@174
   255
	{
dvander@174
   256
		pPlugin->m_ctx_current.ctx->vmbase->FreeContext(pPlugin->m_ctx_current.ctx);
dvander@174
   257
	}
dvander@174
   258
	if (pPlugin->m_ctx_backup.ctx)
dvander@174
   259
	{
dvander@174
   260
		pPlugin->m_ctx_backup.ctx->vmbase->FreeContext(pPlugin->m_ctx_backup.ctx);
dvander@174
   261
	}
dvander@174
   262
dvander@174
   263
	g_pSourcePawn->FreeFromMemory(pPlugin->m_plugin);
dvander@174
   264
dvander@174
   265
	delete pPlugin;
dvander@174
   266
dvander@174
   267
	return true;
dvander@174
   268
}
dvander@174
   269
dvander@174
   270
IPlugin *CPluginManager::FindPluginByContext(const sp_context_t *ctx)
dvander@174
   271
{
dvander@174
   272
	IPlugin *pl = (IPlugin *)ctx->user[SM_CONTEXTVAR_MYSELF];
dvander@174
   273
	return pl;
dvander@174
   274
}
dvander@174
   275
dvander@174
   276
unsigned int CPluginManager::GetPluginCount()
dvander@174
   277
{
dvander@174
   278
	return m_plugins.size();
dvander@174
   279
}
dvander@174
   280
dvander@174
   281
void CPluginManager::AddPluginsListener(IPluginsListener *listener)
dvander@174
   282
{
dvander@174
   283
	m_listeners.push_back(listener);
dvander@174
   284
}
dvander@174
   285
dvander@174
   286
void CPluginManager::RemovePluginsListener(IPluginsListener *listener)
dvander@174
   287
{
dvander@174
   288
	m_listeners.remove(listener);
dvander@174
   289
}
dvander@174
   290
dvander@174
   291
IPluginIterator *CPluginManager::GetPluginIterator()
dvander@174
   292
{
dvander@174
   293
	if (m_iters.empty())
dvander@174
   294
	{
dvander@174
   295
		return new CPluginIterator(&m_plugins);
dvander@174
   296
	} else {
dvander@174
   297
		CPluginIterator *iter = m_iters.front();
dvander@174
   298
		m_iters.pop();
dvander@174
   299
		return iter;
dvander@174
   300
	}
dvander@174
   301
}
dvander@174
   302
dvander@174
   303
void CPluginManager::ReleaseIterator(CPluginIterator *iter)
dvander@174
   304
{
dvander@174
   305
	m_iters.push(iter);
dvander@174
   306
}