2010-12-31 19:13:28 +01:00
|
|
|
/* This file is part of Clementine.
|
|
|
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
|
|
|
|
|
|
|
Clementine 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, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Python.h>
|
2011-01-02 02:07:19 +01:00
|
|
|
#include <sip.h>
|
2010-12-31 19:13:28 +01:00
|
|
|
|
|
|
|
#include "pythonengine.h"
|
|
|
|
#include "pythonscript.h"
|
2011-01-02 02:07:19 +01:00
|
|
|
#include "sipAPIclementine.h"
|
|
|
|
|
|
|
|
#include <QFile>
|
2010-12-31 19:13:28 +01:00
|
|
|
|
2011-01-02 03:23:10 +01:00
|
|
|
const char* PythonEngine::kModulePrefix = "clementinescripts";
|
|
|
|
|
2010-12-31 19:13:28 +01:00
|
|
|
extern "C" {
|
|
|
|
void initclementine();
|
|
|
|
}
|
|
|
|
|
2011-01-02 02:07:19 +01:00
|
|
|
PythonEngine::PythonEngine(ScriptManager* manager)
|
|
|
|
: LanguageEngine(manager),
|
|
|
|
initialised_(false)
|
2010-12-31 19:13:28 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-01-02 02:07:19 +01:00
|
|
|
const sipAPIDef* PythonEngine::GetSIPApi() {
|
|
|
|
#if defined(SIP_USE_PYCAPSULE)
|
|
|
|
return (const sipAPIDef *)PyCapsule_Import("sip._C_API", 0);
|
|
|
|
#else
|
|
|
|
PyObject *sip_module;
|
|
|
|
PyObject *sip_module_dict;
|
|
|
|
PyObject *c_api;
|
|
|
|
|
|
|
|
/* Import the SIP module. */
|
|
|
|
sip_module = PyImport_ImportModule("sip");
|
|
|
|
|
|
|
|
if (sip_module == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Get the module's dictionary. */
|
|
|
|
sip_module_dict = PyModule_GetDict(sip_module);
|
|
|
|
|
|
|
|
/* Get the "_C_API" attribute. */
|
|
|
|
c_api = PyDict_GetItemString(sip_module_dict, "_C_API");
|
|
|
|
|
|
|
|
if (c_api == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Sanity check that it is the right type. */
|
|
|
|
if (!PyCObject_Check(c_api))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Get the actual pointer from the object. */
|
|
|
|
return (const sipAPIDef *)PyCObject_AsVoidPtr(c_api);
|
|
|
|
#endif
|
2010-12-31 21:29:52 +01:00
|
|
|
}
|
|
|
|
|
2011-01-02 02:07:19 +01:00
|
|
|
Script* PythonEngine::CreateScript(const QString& path,
|
|
|
|
const QString& script_file,
|
|
|
|
const QString& id) {
|
2010-12-31 19:13:28 +01:00
|
|
|
// Initialise Python if it hasn't been done yet
|
|
|
|
if (!initialised_) {
|
2011-01-02 02:07:19 +01:00
|
|
|
AddLogLine("Initialising python...", false);
|
|
|
|
|
2010-12-31 19:13:28 +01:00
|
|
|
// Add the Clementine builtin module
|
|
|
|
PyImport_AppendInittab(const_cast<char*>("clementine"), initclementine);
|
|
|
|
|
2011-01-02 02:07:19 +01:00
|
|
|
// Initialise python
|
2010-12-31 19:13:28 +01:00
|
|
|
Py_SetProgramName(const_cast<char*>("clementine"));
|
|
|
|
PyEval_InitThreads();
|
|
|
|
Py_InitializeEx(0);
|
2011-01-02 02:07:19 +01:00
|
|
|
|
|
|
|
// Get the clementine module so we can put stuff in it
|
|
|
|
clementine_module_ = PyImport_ImportModule("clementine");
|
|
|
|
sip_api_ = GetSIPApi();
|
|
|
|
|
|
|
|
// Add objects to the module
|
|
|
|
AddObject(manager()->data().player_, sipType_Player, "player");
|
|
|
|
AddObject(this, sipType_PythonEngine, "pythonengine");
|
2011-01-02 02:33:54 +01:00
|
|
|
|
|
|
|
// Create a module for scripts
|
2011-01-02 03:46:16 +01:00
|
|
|
PyImport_AddModule(kModulePrefix);
|
2011-01-02 02:07:19 +01:00
|
|
|
|
|
|
|
// Run the startup script - this redirects sys.stdout and sys.stderr to our
|
|
|
|
// log handler.
|
|
|
|
QFile python_startup(":pythonstartup.py");
|
|
|
|
python_startup.open(QIODevice::ReadOnly);
|
|
|
|
QByteArray python_startup_script = python_startup.readAll();
|
|
|
|
|
|
|
|
if (PyRun_SimpleString(python_startup_script.constData()) != 0) {
|
|
|
|
AddLogLine("Could not execute startup code", true);
|
|
|
|
Py_Finalize();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-31 19:13:28 +01:00
|
|
|
PyEval_ReleaseLock();
|
|
|
|
|
|
|
|
initialised_ = true;
|
|
|
|
}
|
|
|
|
|
2011-01-02 02:07:19 +01:00
|
|
|
Script* ret = new PythonScript(this, path, script_file, id);
|
2011-01-01 19:37:08 +01:00
|
|
|
if (ret->Init()) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-01-02 03:46:16 +01:00
|
|
|
ret->Unload();
|
2011-01-01 19:37:08 +01:00
|
|
|
delete ret;
|
|
|
|
return NULL;
|
2010-12-31 19:13:28 +01:00
|
|
|
}
|
2011-01-02 02:07:19 +01:00
|
|
|
|
|
|
|
void PythonEngine::AddObject(void* object, const _sipTypeDef* type,
|
|
|
|
const char * name) const {
|
|
|
|
PyObject* python_object = sip_api_->api_convert_from_type(object, type, NULL);
|
|
|
|
PyModule_AddObject(clementine_module_, name, python_object);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PythonEngine::AddLogLine(const QString& message, bool error) {
|
|
|
|
manager()->AddLogLine("Python", message, error);
|
|
|
|
}
|