Skip to content

Commit

Permalink
Commit with lot of changes to make it more C++
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesneimog committed Apr 5, 2024
1 parent 76a986b commit f304a09
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 119 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.15)
include(${CMAKE_CURRENT_SOURCE_DIR}/resources/pd.build/pd.cmake) # pd.build
project(py4pd)
set(CMAKE_CXX_STANDARD 20)

#╭──────────────────────────────────────╮
#│ Python Static Library │
Expand Down Expand Up @@ -43,6 +44,7 @@ endif()
set(NUMPY_INCLUDE_DIR ${NUMPY_INCLUDE_DIR} CACHE PATH "NumPy include directory")
message(STATUS "NumPy include directory: ${NUMPY_INCLUDE_DIR}")


# ──────────────────────────────────────
target_include_directories(py4pd PUBLIC ${NUMPY_INCLUDE_DIR})
target_include_directories(py4pd PUBLIC "/usr/include/python${PYVERSION}")
Expand Down
4 changes: 4 additions & 0 deletions src/ext-class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,10 @@ void *Py4pdNewObj_NewObj(t_symbol *s, int argc, t_atom *argv) {
t_canvas *c = x->canvas;
t_symbol *patch_dir = canvas_getdir(c);
x->objName = gensym(objectName);
bool PdModule = Py4pdUtils_ImportPdModule(x);
if (!PdModule) {
return nullptr;
}
x->zoom = (int)x->canvas->gl_zoom;
x->ignoreOnNone = PyLong_AsLong(ignoreOnNone);
x->outPyPointer = PyLong_AsLong(pyOUT);
Expand Down
5 changes: 5 additions & 0 deletions src/ext-libraries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,11 @@ void *Py4pdLib_NewObj(t_symbol *s, int argc, t_atom *argv) {
t_canvas *c = x->canvas;
t_symbol *patch_dir = canvas_getdir(c);
x->objName = gensym(objectName);
bool PdModule = Py4pdUtils_ImportPdModule(x);
if (!PdModule) {
return nullptr;
}

x->zoom = (int)x->canvas->gl_zoom;
x->ignoreOnNone = PyLong_AsLong(ignoreOnNone);
x->outPyPointer = PyLong_AsLong(pyOUT);
Expand Down
19 changes: 9 additions & 10 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// ======================================================
Dictionary *Py4pdPlayer_CreateDictionary() {
Dictionary *dictionary = (Dictionary *)malloc(sizeof(Dictionary));
dictionary->entries = NULL;
dictionary->entries = nullptr;
dictionary->size = 0;
dictionary->lastOnset = 0;
return dictionary;
Expand All @@ -25,19 +25,19 @@ int Py4pdPlayer_CompareOnset(const void *a, const void *b) {
// ======================================================
KeyValuePair *Py4pdPlayer_PlayerGetValue(Dictionary *dictionary, int onset) {
if (dictionary == NULL) {
return NULL;
return nullptr;
}
for (int i = 0; i < dictionary->size; i++) {
if (dictionary->entries[i].onset == onset) {
return &(dictionary->entries[i]);
}
}
return NULL; // Return NULL if no matching onset is found
return nullptr; // Return NULL if no matching onset is found
}

// ======================================================
void Py4pdPlayer_PlayerSendNewThing(t_py *x, int onset, t_symbol *receiver, PyObject *value) {
if (x->playerDict == NULL) {
if (x->playerDict == nullptr) {
x->playerDict = Py4pdPlayer_CreateDictionary();
}
int index = -1;
Expand Down Expand Up @@ -119,7 +119,7 @@ void Py4pdPlayer_PlayerInsertThing(t_py *x, int onset, PyObject *value) {

// ======================================================
void Py4pdPlayer_FreeDictionary(Dictionary *dictionary) {
if (dictionary == NULL) {
if (dictionary == nullptr) {
return;
}
for (int i = 0; i < dictionary->size; i++) {
Expand All @@ -138,11 +138,10 @@ void Py4pdPlayer_PlayTick(t_py *x) {
}
x->msOnset++;
KeyValuePair *entry = Py4pdPlayer_PlayerGetValue(x->playerDict, x->msOnset);
if (entry != NULL) {
if (entry != nullptr) {
if (entry->isReceiverPlayer) {
// TODO: Implement receiver
} else {
post("[%s]: Playing onset %d", x->objName->s_name, x->msOnset);
for (int i = 0; i < entry->size; i++) {
PyObject *pValue = Py_BuildValue("O", entry->values[i]);
t_py4pd_pValue *pdPyValue = (t_py4pd_pValue *)malloc(sizeof(t_py4pd_pValue));
Expand All @@ -160,7 +159,7 @@ void Py4pdPlayer_PlayTick(t_py *x) {
void Py4pdPlayer_Play(t_py *x, t_symbol *s, int ac, t_atom *av) {
(void)s;
x->msOnset = 0;
if (x->playerDict == NULL) {
if (x->playerDict == nullptr) {
pd_error(x, "[%s]: Nothing to play.", x->objName->s_name);
return;
}
Expand All @@ -174,7 +173,7 @@ void Py4pdPlayer_Play(t_py *x, t_symbol *s, int ac, t_atom *av) {

// ======================================================
void Py4pdPlayer_Stop(t_py *x) {
if (x->playerClock == NULL) {
if (x->playerClock == nullptr) {
pd_error(x, "[%s]: Nothing to stop.", x->objName->s_name);
return;
}
Expand All @@ -184,7 +183,7 @@ void Py4pdPlayer_Stop(t_py *x) {

// ======================================================
void Py4pdPlayer_Clear(t_py *x) {
if (x->playerClock != NULL) {
if (x->playerClock != nullptr) {
clock_unset(x->playerClock);
}
Py4pdPlayer_FreeDictionary(x->playerDict);
Expand Down
88 changes: 43 additions & 45 deletions src/py4pd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,44 +29,40 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {
pd_error(x, "[py4pd] Too many arguments! Usage: py4pd -lib <library_name>");
return -1;
}
const char *oldName = atom_gensym(argv + 1)->s_name;
char newName[MAXPDSTRING];
int j;
for (j = 0; oldName[j] != '\0'; j++) {
newName[j] = (oldName[j] == '-') ? '_' : oldName[j];
}
newName[j] = '\0';
t_symbol *scriptFileName = gensym(newName);

char script_file_path[MAXPDSTRING];
snprintf(script_file_path, MAXPDSTRING, "%s/%s.py", x->pdPatchPath->s_name,
atom_gensym(argv + 1)->s_name);
t_symbol *libName = atom_gensym(argv + 1);
std::string funcLibName = Py4pdUtils_GetLibFuncName(libName);

char script_inside_py4pd_path[MAXPDSTRING];
snprintf(script_inside_py4pd_path, MAXPDSTRING, "%s/resources/py4pd-mod/%s.py",
x->py4pdPath->s_name, atom_gensym(argv + 1)->s_name);
// first check if file exists
std::string pLibPathLocal = x->pdPatchPath->s_name;
pLibPathLocal += "/";
pLibPathLocal += libName->s_name;
pLibPathLocal += ".py";

// global path
std::string pLibPathGlobal = x->py4pdPath->s_name;
pLibPathGlobal += "/resources/py-modules/";
pLibPathGlobal += libName->s_name;

PyObject *sysPath = PySys_GetObject("path");
if (access(script_file_path, F_OK) == -1 && access(script_inside_py4pd_path, F_OK) == -1) {
Py_XDECREF(x->pFunction);
if (!std::filesystem::exists(pLibPathGlobal) && !std::filesystem::exists(pLibPathLocal)) {
// check in Pd Search Paths
int libraryNotFound = 1;
for (int i = 0; 1; i++) {
char const *pathelem = namelist_get(STUFF->st_searchpath, i);
if (!pathelem) {
char const *Path = namelist_get(STUFF->st_searchpath, i);
if (!Path) {
break;
}
char *library_path =
(char *)malloc(strlen(pathelem) + strlen(scriptFileName->s_name) + 1);
snprintf(library_path, MAXPDSTRING, "%s/%s/", pathelem, atom_gensym(argv + 1)->s_name);

if (access(library_path, F_OK) != -1) { // Library founded
std::string PdPathsLibPath = Path;
PdPathsLibPath += "/";
PdPathsLibPath += libName->s_name;
if (std::filesystem::exists(PdPathsLibPath)) {
libraryNotFound = 0;
PyList_Append(sysPath, PyUnicode_FromString(library_path));
PyList_Append(sysPath, PyUnicode_FromString(PdPathsLibPath.c_str()));
}
free(library_path);
}
if (libraryNotFound) {
pd_error(x, "[py4pd] Library file '%s.py' not found!", scriptFileName->s_name);
pd_error(x, "[py4pd] Library file '%s.py' not found!", libName->s_name);
return -1;
}
}
Expand All @@ -91,7 +87,7 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {

t_py *prev_obj = nullptr;
int prev_obj_exists = 0;
PyObject *MainModule = PyImport_ImportModule("pd");
PyObject *MainModule = x->InternalModule;
PyObject *oldObjectCapsule;

if (MainModule != nullptr) {
Expand All @@ -114,7 +110,7 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {
}
pModule = PyImport_ImportModule(atom_gensym(argv + 1)->s_name);
if (pModule == nullptr) {
pd_error(x, "[Python] Failed to load script file %s", scriptFileName->s_name);
pd_error(x, "[Python] Failed to load script file %s", libName->s_name);
Py4pdUtils_PrintError(x);
Py_XDECREF(pModule);
Py_XDECREF(MainModule);
Expand All @@ -132,14 +128,11 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {
Py_XDECREF(MainModule);
return -1;
}

PyObject *pModuleDict = PyModule_GetDict(pModule);

if (pModuleDict == nullptr) {
pd_error(x, "[Python] Failed to get script file dictionary");
return -1;
}

PyObject *pFilenameObj = PyDict_GetItemString(pModuleDict, "__file__");
if (!pFilenameObj) {
pd_error(x, "[Python] Failed to get script file path");
Expand All @@ -148,12 +141,10 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {
return -1;
}
// convert const char * to char *
char *libraryFolder = (char *)malloc(strlen(PyUnicode_AsUTF8(pFilenameObj)) + 1);
Py4pdUtils_Strlcpy(libraryFolder, PyUnicode_AsUTF8(pFilenameObj),
strlen(PyUnicode_AsUTF8(pFilenameObj)) + 1);
std::string libFolder = PyUnicode_AsUTF8(pFilenameObj);

x->libraryFolder = gensym(Py4pdUtils_GetFolderName(libraryFolder));
free(libraryFolder);
// TODO: Fix this
x->libraryFolder = gensym(Py4pdUtils_GetFolderName((char *)libFolder.c_str()));

if (pModule == NULL) {
Py4pdUtils_PrintError(x);
Expand All @@ -164,26 +155,25 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {

// check if module has the function Py4pdLoadObjects or
// "sScriptFilename + setup"
char *setupFuncName = (char *)malloc(strlen(scriptFileName->s_name) + 7);
snprintf(setupFuncName, strlen(scriptFileName->s_name) + 7, "%s_setup", scriptFileName->s_name);
PyObject *pFuncName = PyUnicode_FromString(setupFuncName);
t_symbol *pFuncNameSymbol = gensym(setupFuncName);
std::string Func2Call = funcLibName;
Func2Call += "_setup";

PyObject *pFuncName = PyUnicode_FromString(Func2Call.c_str());
t_symbol *pFuncNameSymbol = gensym(Func2Call.c_str());
pFunc = PyObject_GetAttr(pModule, pFuncName);
if (pFunc == NULL) {
Py_DECREF(pFuncName);
pFuncName = PyUnicode_FromString("py4pdLoadObjects");
Py_XDECREF(pFunc);
pFunc = PyObject_GetAttr(pModule, pFuncName);
if (pFunc == NULL) {
pd_error(x, "[Python] Failed to load function %s", setupFuncName);
pd_error(x, "[Python] Failed to load function %s", Func2Call.c_str());
Py4pdUtils_PrintError(x);
Py_XDECREF(pModule);
free(setupFuncName);
return -1;
}
pFuncNameSymbol = gensym("Py4pdLoadObjects");
}
free(setupFuncName);

if (pFunc && PyCallable_Check(pFunc)) {
if (objectCapsule == NULL) {
Expand Down Expand Up @@ -220,14 +210,14 @@ static int Py4pd_LibraryLoad(t_py *x, int argc, t_atom *argv) {
}
x->pModule = pModule;
x->pFunction = pFunc;
x->pScriptName = scriptFileName;
x->pScriptName = libName;
x->pFuncName = pFuncNameSymbol;
x->funcCalled = 1;
x->isLib = 1;
Py_XDECREF(MainModule);
Py_XDECREF(pModuleReloaded);
Py_XDECREF(pValue);
logpost(x, 3, "[py4pd] Library %s loaded!", scriptFileName->s_name);
logpost(x, 3, "[py4pd] Library %s loaded!", libName->s_name);
printf("%s Loaded\n", atom_gensym(argv + 1)->s_name);
} else {
x->funcCalled = 1; // set the flag to 0 because it crash Pd if
Expand Down Expand Up @@ -1123,6 +1113,10 @@ static void *Py4pd_Py4pdNew(t_symbol *s, int argc, t_atom *argv) {
patchDir = gensym(new_path);
free(new_path);
}
bool PdModule = Py4pdUtils_ImportPdModule(x);
if (!PdModule) {
return nullptr;
}
x->zoom = (int)x->canvas->gl_zoom;
x->audioInput = 0;
x->audioOutput = 0;
Expand All @@ -1149,6 +1143,10 @@ static void *Py4pd_Py4pdNew(t_symbol *s, int argc, t_atom *argv) {
x = (t_py *)pd_new(py4pd_classLibrary);
x->canvas = canvas_getcurrent();
t_canvas *c = x->canvas;
bool PdModule = Py4pdUtils_ImportPdModule(x);
if (!PdModule) {
return nullptr;
}
x->zoom = (int)x->canvas->gl_zoom;
t_symbol *patchDir = canvas_getdir(c);
if (patchDir->s_name[strlen(patchDir->s_name) - 1] != '/') {
Expand Down
11 changes: 7 additions & 4 deletions src/py4pd.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@

#include <m_pd.h>

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
extern "C" {
#endif
#include <g_canvas.h>
#include <s_stuff.h> // get the search paths
#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
}
#endif

//
#include <pthread.h>
#include <dirent.h>

#include <thread>
#include <string>
#include <filesystem>


#define PY_SSIZE_T_CLEAN // Remove deprecated functions
#include <Python.h>

Expand Down Expand Up @@ -134,6 +135,8 @@ typedef struct _py { // It seems that all the objects are some kind of class.
t_outlet *mainOut; // outlet 1.
t_inlet *mainIn; // intlet 1

PyObject *InternalModule; // Internal Module

// TESTING THINGS
t_py4pd_pValue **pyObjArgs; // Obj Variables Arguments
pdcollectHash *pdcollect; // hash table to store the objects
Expand Down
Loading

0 comments on commit f304a09

Please sign in to comment.