diff options
-rw-r--r-- | pdoctave.c | 130 | ||||
-rw-r--r-- | pdoctave.h | 6 | ||||
-rw-r--r-- | pdoctave.pd | 20 | ||||
-rw-r--r-- | pdoctave_command.c | 114 | ||||
-rw-r--r-- | pdoctave_command.h | 5 | ||||
-rw-r--r-- | pdoctave_dataframe.c | 249 | ||||
-rw-r--r-- | pdoctave_dataframe.h | 66 | ||||
-rw-r--r-- | pdoctave_datatypes.h | 7 | ||||
-rw-r--r-- | pdoctave_get.c | 183 | ||||
-rw-r--r-- | pdoctave_get.h | 5 | ||||
-rw-r--r-- | pdoctave_send.c | 150 | ||||
-rw-r--r-- | pdoctave_send.h | 5 | ||||
-rw-r--r-- | read_shared_mem.cc | 99 | ||||
-rw-r--r-- | test.cc | 10 | ||||
-rw-r--r-- | test_pdoctave.pd | 80 | ||||
-rw-r--r-- | write_shared_mem.cc | 105 |
16 files changed, 1234 insertions, 0 deletions
diff --git a/pdoctave.c b/pdoctave.c new file mode 100644 index 0000000..31cd69b --- /dev/null +++ b/pdoctave.c @@ -0,0 +1,130 @@ +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <sys/shm.h> +#include <sys/ipc.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <stdio.h> +#ifndef __pdoctave_c__ +#include "m_pd.h" +#include "pdoctave_send.h" +#include "pdoctave_get.h" +#include "pdoctave_command.h" +//#include "math.h" +//#include "d_mayer_fft.c" +//#include "/home/fzotter/downloads/pd-0.38-4/src/d_mayer_fft.c" +//#include "/home/pd/src/pd-0.37-1-alsamm/src/d_mayer_fft.c" + +static t_class *pdoctave_class; +static int obj_instances = 0; +static int octave_pid; +static int fd[2]; + + +/* PDOCTAVE is an object that starts an octave process and holds a pipe to its stdin. + * other sub-routines can use the 'writeToOctaveStdIN' routine to write commands + * to octave. +*/ + + +typedef struct _PDOctave_ PDOctave; +struct _PDOctave_ +{ + t_object x_obj; +}; + +int getPDOctaveInstances () +{ + return obj_instances; +} + +// writing commands to the octave-process +int writeToOctaveStdIN (const char *cmd) +{ + int bytes_written; + if (obj_instances > 0) { + bytes_written = write(fd[1], (void*)cmd, strlen(cmd)); + if (bytes_written == -1) { + post("error writing to pipe"); + return -1; + } +// post("wrote %d bytes", bytes_written); + return 0; + } + else + return -1; +} + +static void deletePDOctave (PDOctave *pdoctave_obj) +{ + if (obj_instances-- == 1) { + int err = 0; + close(fd[1]); + + if ((waitpid(octave_pid, NULL, 0) == -1) && (errno != ECHILD)) { + err = 1; + } + if (err) { + post("error closing octave"); + } + } +} + + +static void *newPDOctave (t_symbol *s, int argc, t_atom *argv) +{ + PDOctave * pdoctave_obj; + pdoctave_obj = (PDOctave *) pd_new (pdoctave_class); + + // creating only one pipe! + if (!obj_instances++) { + + if (pipe(fd) == -1) { + post("Error creating pipe."); + } + + if ((octave_pid = fork()) == 0) { /* child process */ + // execution of octave and pipe to octave stdin + close(fd[1]); + + if (dup2(fd[0], STDIN_FILENO) == -1) { + post("error duplicating filedescriptor to STDIN"); + exit(1); + return; + } + + close(fd[0]); + execlp("octave", "octave", "-i", NULL); + // this is only reached, when the octave process is + // dying before the pdoctave object + post("shell command ``octave'' could not be executed"); + } else if (octave_pid == -1) { + // Error handling + } else { /* parent process */ + close(fd[0]); + // waiting for the child process having the octave pipe + // and process properly set up + sleep(1); + } + } + return ((void *) pdoctave_obj); +} + +void pdoctave_setup (void) +{ + pdoctave_class = class_new + (gensym("pdoctave"), + (t_newmethod) newPDOctave, + (t_method) deletePDOctave, + sizeof (PDOctave), + CLASS_NOINLET, 0); + post("pdoctave successfully loaded!"); + pdoctave_send_setup (); + pdoctave_command_setup (); + pdoctave_get_setup (); +} + +#define __pdoctave_c_ +#endif diff --git a/pdoctave.h b/pdoctave.h new file mode 100644 index 0000000..9678863 --- /dev/null +++ b/pdoctave.h @@ -0,0 +1,6 @@ +// pdoctave functions + +// functions return -1 when they fail (= octave object is not instanciated in pd) + +int getPDOctaveInstances (); +int writeToOctaveStdIN (const char *cmd); diff --git a/pdoctave.pd b/pdoctave.pd new file mode 100644 index 0000000..0cd232f --- /dev/null +++ b/pdoctave.pd @@ -0,0 +1,20 @@ +#N canvas 576 230 660 659 10; +#X obj 103 514 shell; +#X obj 376 509 table octave 100; +#X obj 326 429 textfile; +#X msg 366 305 clear; +#X msg 333 272 write octave_matrix.m; +#X obj 177 522 print; +#X msg 340 345 add clearplot() \, add load octave_matrix.mtx \, add +plot(octave_matrix) \, add grid on \, add pause(2); +#X msg 100 453 konsole -e octave /home/fzotter/Documents/Arbeit/ConferenceSystem/octave_matrix.m +; +#X msg 92 387 konsole -e octave; +#X msg 146 572 \; octave write /home/fzotter/Documents/Arbeit/ConferenceSystem/octave_matrix.mtx +; +#X connect 3 0 2 0; +#X connect 4 0 2 0; +#X connect 6 0 2 0; +#X connect 7 0 0 0; +#X connect 7 0 5 0; +#X connect 8 0 0 0; diff --git a/pdoctave_command.c b/pdoctave_command.c new file mode 100644 index 0000000..b1f1d6b --- /dev/null +++ b/pdoctave_command.c @@ -0,0 +1,114 @@ +#include <string.h> +#ifndef __pdoctave_command_c_ +#define __pdoctave_command_c_ +#include "pdoctave.h" /* writing a command to octave */ +#include "pdoctave_dataframe.h" +#include "m_pd.h" + +static t_class *pdoctave_command_class; + +typedef struct _PDOctaveCommand_ PDOctaveCommand; +struct _PDOctaveCommand_ +{ + t_object x_obj; + char oct_command[1024]; + int pos; +}; + +static void clearStringCommand (PDOctaveCommand *pdoctcmd_obj) +{ + pdoctcmd_obj->pos=0; + pdoctcmd_obj->oct_command[0] = '\0'; +} + +static void addStringToCommand (PDOctaveCommand *pdoctcmd_obj, char *str) +{ + int n = strlen (str); + strcpy(pdoctcmd_obj->oct_command+pdoctcmd_obj->pos, str); + pdoctcmd_obj->pos += n; +} + +static void addAtomToCommand (PDOctaveCommand *pdoctcmd_obj, t_atom *a) +{ + const unsigned int bufsize = 50; + char str[bufsize]; + + atom_string (a, str, bufsize); + + if (strcmp(str,"\\\\,") == 0) { + strcpy(str,",\0"); + } + else if (strcmp(str,"\\\\;") == 0) { + strcpy(str,";\0"); + } + + addStringToCommand (pdoctcmd_obj, str); +} + +static void removeEscapeSlashes (char *c) +{ + int pos = strlen(c); + c = c+pos-1; + + while (--pos) { + if (*--c == '\\') { + strcpy(c,c+1); + } + } +} +static void pDOctaveCommandBang (PDOctaveCommand *pdoctcmd_obj) +{ + post("command: %s sent", pdoctcmd_obj->oct_command); + writeToOctaveStdIN (pdoctcmd_obj->oct_command); +} + + +static void pDOctaveCommandAny (PDOctaveCommand *pdoctcmd_obj, t_symbol *s, int argc, t_atom *argv) +{ + clearStringCommand (pdoctcmd_obj); + if (argc>0) + while (argc--) { + addAtomToCommand (pdoctcmd_obj, argv++); + addStringToCommand (pdoctcmd_obj, " \0"); + } + + addStringToCommand (pdoctcmd_obj, "\n"); + removeEscapeSlashes (pdoctcmd_obj->oct_command); + pDOctaveCommandBang (pdoctcmd_obj); +} + +static void *newPDOctaveCommand (t_symbol *s, int argc, t_atom *argv) +{ + PDOctaveCommand *pdoctcmd_obj = (PDOctaveCommand *) + pd_new (pdoctave_command_class); + + post("getpdoctaveinstances returned %d", getPDOctaveInstances()); + if (getPDOctaveInstances()<1) { + post("Octave not running, insert a 'pdoctave' object!!"); + } + pdoctcmd_obj->pos = 0; + if (argc>0) + while (argc--) { + addAtomToCommand (pdoctcmd_obj, argv++); + addStringToCommand (pdoctcmd_obj, " \0"); + } + + addStringToCommand (pdoctcmd_obj, "\n"); + removeEscapeSlashes(pdoctcmd_obj->oct_command); + + return ((void *) pdoctcmd_obj); +} +void pdoctave_command_setup (void) +{ + pdoctave_command_class = class_new + (gensym("pdoctave_command"), + (t_newmethod) newPDOctaveCommand, + 0, + sizeof (PDOctaveCommand), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (pdoctave_command_class, (t_method) pDOctaveCommandBang); + class_addanything (pdoctave_command_class, (t_method) pDOctaveCommandAny); + post("pdoctave_command successfully loaded"); +} +#endif + diff --git a/pdoctave_command.h b/pdoctave_command.h new file mode 100644 index 0000000..7250c89 --- /dev/null +++ b/pdoctave_command.h @@ -0,0 +1,5 @@ +#ifndef __pdoctave_command_h_ +#define __pdoctave_command_h_ +void pdoctave_command_setup (void); +#endif + diff --git a/pdoctave_dataframe.c b/pdoctave_dataframe.c new file mode 100644 index 0000000..7193c62 --- /dev/null +++ b/pdoctave_dataframe.c @@ -0,0 +1,249 @@ +#include "pdoctave_dataframe.h" + +SharedDataFrame *newSharedDataFrame () +{ + int id; + SharedDataFrame *sdf; + + id = shmget (IPC_PRIVATE, sizeof(SharedDataFrame), + SHM_R | SHM_W); + + if (id == -1) return 0; + + sdf = shmat (id, 0, 0); + + if (sdf == (SharedDataFrame *) -1) { + shmctl (id, IPC_RMID, 0); + return 0; + } + + sdf->frame_attached = 1; + sdf->data_attached = 0; + sdf->data_frame_id = id; + sdf->data_vec_id = -1; + sdf->block_for_write = 0; + sdf->block_for_read = 0; + + return sdf; +} + + +SharedDataFrame *getSharedDataFrame (int id) +{ + SharedDataFrame *sdf; + + sdf = shmat (id, 0, 0); + + if (sdf == (SharedDataFrame *) -1) + return 0; + + sdf->frame_attached++; + + return sdf; +} + + + + +void freeSharedDataFrame (SharedDataFrame **sdf) +{ + SharedDataFrame *sdfp = *sdf; + if (sdfp) { + if (sdfp->frame_attached > 0) + sdfp->frame_attached--; + shmdt(sdfp); + *sdf = 0; + } +} + + +void removeSharedDataFrame (SharedDataFrame **sdf) +{ + int id; + SharedDataFrame *sdfp = *sdf; + if (sdfp) { + id = sdfp->data_frame_id; + if (sdfp->frame_attached > 0) + shmdt (sdfp); + if (id != -1) + shmctl(id, IPC_RMID, 0); + *sdf = 0; + } +} + + +int getSharedDataFrameId (SharedDataFrame *sdf) +{ + if (sdf) + return sdf->data_frame_id; + else + return -1; +} + + + +DatTyp getSharedDataType (SharedDataFrame *sdf) +{ + if (sdf) + return sdf->data_typ; + else + return UNKNOWN; +} + + +int getSharedDataVecLength (SharedDataFrame *sdf) +{ + if (sdf) + return sdf->data_vec_len; + else + return 0; +} + + +void *newSharedData (SharedDataFrame *sdf, int n, int size_bytes, DatTyp dtyp) +{ + void *data; + int id; + + if (sdf) { + + id = sdf->data_vec_id; + if (id == -1) + id = shmget(IPC_PRIVATE, n*size_bytes, SHM_R | SHM_W); + + if (id == -1) return 0; + + data = shmat(id,0,0); + + if (data == (void *) -1) { + shmctl (id, IPC_RMID, 0); + return 0; + } + + sdf->data_attached = 1; + sdf->data_size_bytes = size_bytes; + sdf->data_vec_len = n; + sdf->data_vec_id = id; + sdf->data_typ = dtyp; + + return data; + } + else return 0; +} + + +void *getSharedData (SharedDataFrame *sdf) +{ + void *data; + + if ((sdf)&&(sdf->data_vec_id != -1)) { + + data = shmat(sdf->data_vec_id,0,0); + + if (data == (void *) -1) { + return 0; + } + + sdf->data_attached++; + + return data; + } + else + return 0; +} + + +void freeSharedData (SharedDataFrame *sdf, void **data) +{ + void *datap = *data; + if (datap) { + shmdt(datap); + *data = 0; + if ((sdf)&&(sdf->data_attached > 0)) + sdf->data_attached--; + } +} + + +void removeSharedData (SharedDataFrame *sdf, void **data) +{ + int id; + void *datap = *data; + if (datap) { + shmdt (datap); + *data = 0; + if (sdf) { + if (sdf->data_attached > 0) + sdf->data_attached--; + if (sdf->data_vec_id != -1) { + shmctl (sdf->data_vec_id, IPC_RMID, 0); + sdf->data_vec_id = -1; + } + } + } +} + +void unBlockForReading (SharedDataFrame *sdf) +{ + if (sdf) + sdf->block_for_read = 0; +} +void unBlockForWriting (SharedDataFrame *sdf) +{ + if (sdf) + sdf->block_for_write = 0; +} +void blockForReading (SharedDataFrame *sdf) +{ + if (sdf) + sdf->block_for_read = 1; +} +void blockForWriting (SharedDataFrame *sdf) +{ + if (sdf) + sdf->block_for_write = 1; +} +void sleepUntilReadUnBlocked (SharedDataFrame *sdf, int usleep_time) +{ + int timer = 0; + if (sdf) { + while ((sdf->block_for_read!=0)&&(timer < MAX_SLEEP_TIME)) { + timer += usleep_time; + usleep (usleep_time); + } + } +} +void sleepUntilReadBlocked (SharedDataFrame *sdf, int usleep_time) +{ + int timer = 0; + if (sdf) { + while ((sdf->block_for_read==0)&&(timer < MAX_SLEEP_TIME)) { + timer +=usleep_time; + usleep (usleep_time); + } + + } +} +void sleepUntilWriteUnBlocked (SharedDataFrame *sdf, int usleep_time) +{ + int timer = 0; + if (sdf) { + while ((sdf->block_for_write!=0)&&(timer < MAX_SLEEP_TIME)) { + timer +=usleep_time; + usleep (usleep_time); + } + + } +} +void sleepUntilWriteBlocked (SharedDataFrame *sdf, int usleep_time) +{ + int timer = 0; + if (sdf) { + while ((sdf->block_for_write==0)&&(timer < MAX_SLEEP_TIME)) { + timer +=usleep_time; + usleep (usleep_time); + } + + } +} + diff --git a/pdoctave_dataframe.h b/pdoctave_dataframe.h new file mode 100644 index 0000000..53a21cc --- /dev/null +++ b/pdoctave_dataframe.h @@ -0,0 +1,66 @@ +#ifndef __pdoctave_data_frame_h__ +#define __pdoctave_data_frame_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <unistd.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/ipc.h> +#include <sys/wait.h> +#include <stdio.h> + +#include "pdoctave_datatypes.h" + +#define STD_USLEEP_TIME 100 +#define MAX_SLEEP_TIME 200000 + +typedef struct _SharedDataFrame_ SharedDataFrame; + +struct _SharedDataFrame_ { + int data_frame_id; + + int data_vec_id; + int data_vec_len; + int data_size_bytes; + DatTyp data_typ; + + // internal states + int frame_attached; + int data_attached; + + int block_for_read; + int block_for_write; +}; + +SharedDataFrame *newSharedDataFrame (); +SharedDataFrame *getSharedDataFrame (int id); +void freeSharedDataFrame (SharedDataFrame **sdf); +void removeSharedDataFrame (SharedDataFrame **sdf); +int getSharedDataFrameId (SharedDataFrame *sdf); + +DatTyp getSharedDataType (SharedDataFrame *sdf); +int getSharedDataVecLength (SharedDataFrame *sdf); + +void *newSharedData (SharedDataFrame *sdf, int n, int size_bytes, DatTyp dtyp); +void *getSharedData (SharedDataFrame *sdf); +void freeSharedData (SharedDataFrame *sdf, void **data); +void removeSharedData (SharedDataFrame *sdf, void **data); + +void unBlockForReading (SharedDataFrame *sdf); +void unBlockForWriting (SharedDataFrame *sdf); +void blockForReading (SharedDataFrame *sdf); +void blockForWriting (SharedDataFrame *sdf); +void sleepUntilReadUnBlocked (SharedDataFrame *sdf, int usleep_time); +void sleepUntilReadBlocked (SharedDataFrame *sdf, int usleep_time); +void sleepUntilWriteUnBlocked (SharedDataFrame *sdf, int usleep_time); +void sleepUntilWriteBlocked (SharedDataFrame *sdf, int usleep_time); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pdoctave_datatypes.h b/pdoctave_datatypes.h new file mode 100644 index 0000000..603e055 --- /dev/null +++ b/pdoctave_datatypes.h @@ -0,0 +1,7 @@ +typedef enum { + MATRIX, + FLOAT, + LIST, + SYMBOL, + UNKNOWN +} DatTyp; diff --git a/pdoctave_get.c b/pdoctave_get.c new file mode 100644 index 0000000..1c7df7b --- /dev/null +++ b/pdoctave_get.c @@ -0,0 +1,183 @@ +#include <string.h> +#ifndef __pdoctave_get_c_ +#define __pdoctave_get_c_ +#include "pdoctave.h" /* writing a command to octave */ +#include "pdoctave_dataframe.h" +#include "m_pd.h" + +static t_class *pdoctave_get_class; + +typedef struct _PDOctaveGet_ PDOctaveGet; +struct _PDOctaveGet_ +{ + t_object x_obj; + t_outlet *outlet; + SharedDataFrame *sdf; + char oct_command[150]; + char *oct_name; + void *data; + int list_length; + t_atom *list; +}; + +static void *newPDOctaveGet (t_symbol *s, int argc, t_atom *argv) +{ + PDOctaveGet *pdoctget_obj = (PDOctaveGet *) + pd_new (pdoctave_get_class); + t_symbol *name; + + post("getpdoctaveinstances returned %d", getPDOctaveInstances()); + if (getPDOctaveInstances()<1) { + post("Octave not running, insert a 'pdoctave' object!!"); + } + if (argc>0) + name = atom_getsymbol(argv); + else + name = gensym ("pdm1"); + + pdoctget_obj->sdf = newSharedDataFrame (); + pdoctget_obj->data = 0; + pdoctget_obj->oct_name = name->s_name; + pdoctget_obj->outlet = outlet_new (&pdoctget_obj->x_obj, 0); + + return ((void *) pdoctget_obj); +} + +static void pDOctaveGetCommand (PDOctaveGet *pdoctget_obj) +{ + char *cmd; + cmd = pdoctget_obj->oct_command; + strcpy(cmd, "write_shared_mem("); + cmd += 17; + strcpy(cmd, pdoctget_obj->oct_name); + cmd += strlen (cmd); + *cmd++ = ','; + sprintf(cmd, "%d", getSharedDataFrameId(pdoctget_obj->sdf)); + cmd += strlen(cmd); + strcpy (cmd, ")\n"); + + writeToOctaveStdIN (pdoctget_obj->oct_command); +} + +static void copyFloats (float *f, t_atom *a, int n) +{ + for (;n--;a++,f++) + SETFLOAT (a, *f); +} + +static void outletListAllocation (PDOctaveGet *pdoctget_obj, int newsize) +{ + if (newsize != pdoctget_obj->list_length) { + if (newsize > 0) { + if (pdoctget_obj->list_length > 0) { + pdoctget_obj->list = (t_atom *) + resizebytes (pdoctget_obj->list, + sizeof(t_atom) * pdoctget_obj->list_length, + sizeof(t_atom) * newsize); + pdoctget_obj->list_length = newsize; + } + else { + pdoctget_obj->list = (t_atom *) getbytes (sizeof(t_atom) * newsize); + pdoctget_obj->list_length = newsize; + } + } + else if (newsize == 0) { + freebytes (pdoctget_obj->list, sizeof(t_atom) * pdoctget_obj->list_length); + pdoctget_obj->list = 0; + pdoctget_obj->list_length = 0; + } + } +} + +static void pdoctaveConvertData (PDOctaveGet *pdoctget_obj) +{ + int size = getSharedDataVecLength(pdoctget_obj->sdf); + t_symbol *s; + switch (getSharedDataType (pdoctget_obj->sdf)) { + case FLOAT: + case MATRIX: + case LIST: + outletListAllocation (pdoctget_obj, size); + copyFloats ((float *) pdoctget_obj->data, pdoctget_obj->list, size); + break; + case SYMBOL: + size = 1; + outletListAllocation (pdoctget_obj, 1); + s = gensym((char*)pdoctget_obj->data); + SETSYMBOL (pdoctget_obj->list, s); + break; + case UNKNOWN: + post("pdoctave_get: unknown return value"); + } + removeSharedData (pdoctget_obj->sdf, &(pdoctget_obj->data)); +} + +static void pdoctaveOutletList (PDOctaveGet *pdoctget_obj) +{ + t_symbol *s; + switch (getSharedDataType (pdoctget_obj->sdf)) { + case FLOAT: + s = gensym("float"); + break; + case LIST: + s = gensym("list"); + break; + case MATRIX: + s = gensym("matrix"); + break; + case SYMBOL: + s = gensym("symbol"); + break; + case UNKNOWN: + post("pdoctave_get: unknown return value"); + return; + } + outlet_anything (pdoctget_obj->outlet, + s, pdoctget_obj->list_length, pdoctget_obj->list); +} + +static void pDOctaveGetBang (PDOctaveGet *pdoctget_obj) +{ + SharedDataFrame *sdf; + + sdf = pdoctget_obj->sdf; + + sleepUntilReadUnBlocked (sdf,STD_USLEEP_TIME); + blockForReading (sdf); + + // sending read command + blockForWriting (sdf); + pDOctaveGetCommand (pdoctget_obj); + sleepUntilWriteUnBlocked (sdf,STD_USLEEP_TIME); + + // waiting for results + pdoctget_obj->data = getSharedData (sdf); + + // converting incoming data + pdoctaveConvertData (pdoctget_obj); + unBlockForReading (sdf); + + // outletting data + pdoctaveOutletList (pdoctget_obj); +} + + +static void deletePDOctaveGet (PDOctaveGet *pdoctget_obj) +{ + removeSharedData (pdoctget_obj->sdf, &(pdoctget_obj->data)); + removeSharedDataFrame (&(pdoctget_obj->sdf)); +} + +void pdoctave_get_setup (void) +{ + pdoctave_get_class = class_new + (gensym("pdoctave_get"), + (t_newmethod) newPDOctaveGet, + (t_method) deletePDOctaveGet, + sizeof (PDOctaveGet), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (pdoctave_get_class, (t_method) pDOctaveGetBang); + post("pdoctave_get successfully loaded"); +} +#endif + diff --git a/pdoctave_get.h b/pdoctave_get.h new file mode 100644 index 0000000..f408b1b --- /dev/null +++ b/pdoctave_get.h @@ -0,0 +1,5 @@ +#ifndef __pdoctave_send_h_ +#define __pdoctave_send_h_ +void pdoctave_send_setup (void); +#endif + diff --git a/pdoctave_send.c b/pdoctave_send.c new file mode 100644 index 0000000..b6a38d4 --- /dev/null +++ b/pdoctave_send.c @@ -0,0 +1,150 @@ +#include <string.h> +#ifndef __pdoctave_send_c_ +#define __pdoctave_send_c_ +#include "pdoctave.h" /* writing a command to octave */ +#include "pdoctave_dataframe.h" +#include "m_pd.h" + +static t_class *pdoctave_send_class; + +typedef struct _PDOctaveSend_ PDOctaveSend; +struct _PDOctaveSend_ +{ + t_object x_obj; + SharedDataFrame *sdf; + char oct_command[150]; + char *oct_name; + void *data; +}; + +static void *newPDOctaveSend (t_symbol *s, int argc, t_atom *argv) +{ + PDOctaveSend *pdoctsnd_obj = (PDOctaveSend *) + pd_new (pdoctave_send_class); + t_symbol *name; + + if (getPDOctaveInstances()<1) { + post("Octave not running, insert a 'pdoctave' object!!"); + } + if (argc>0) + name = atom_getsymbol(argv); + else + name = gensym ("pdm1"); + + pdoctsnd_obj->sdf = newSharedDataFrame (); + pdoctsnd_obj->data = 0; + pdoctsnd_obj->oct_name = name->s_name; + + return ((void *) pdoctsnd_obj); +} + +static void pDOctaveSendBang (PDOctaveSend *pdoctsnd_obj) +{ + char *cmd; + strcpy(pdoctsnd_obj->oct_command, pdoctsnd_obj->oct_name); + cmd = pdoctsnd_obj->oct_command + strlen(pdoctsnd_obj->oct_name); + strcpy(cmd, "=read_shared_mem("); + cmd += 17; + sprintf(cmd, "%d", getSharedDataFrameId(pdoctsnd_obj->sdf)); + cmd = cmd+strlen(cmd); + strcpy (cmd, ");\n"); + + writeToOctaveStdIN (pdoctsnd_obj->oct_command); + freeSharedData (pdoctsnd_obj->sdf, &(pdoctsnd_obj->data)); + //removeSharedData (pdoctsnd_obj->sdf, &(pdoctsnd_obj->data)); +} + +static void copyFloats (float *f, t_atom *a, int n) +{ + for (;n--;a++,f++) + *f = atom_getfloat(a); +} + +static DatTyp pdSelectorClassify (char *selector) +{ + DatTyp pdtyp; + if (!strcmp (selector, "matrix")) + pdtyp = MATRIX; + else if (!strcmp (selector, "float")) + pdtyp = FLOAT; + else if (!strcmp (selector, "list")) + pdtyp = LIST; + else if (!strcmp (selector, "symbol")) + pdtyp = SYMBOL; + else + pdtyp = UNKNOWN; + return pdtyp; +} + +static void pDOctaveSend (PDOctaveSend *pdoctsnd_obj, + t_symbol *s, int argc, t_atom *argv) +{ + DatTyp pdtyp; + SharedDataFrame *sdf; + + char *selector = s->s_name; + t_symbol *symptr; + float *f; + char *c; + int count = argc; + + pdtyp = pdSelectorClassify (selector); + + sdf = pdoctsnd_obj->sdf; + + sleepUntilWriteUnBlocked (sdf, STD_USLEEP_TIME); + blockForWriting (sdf); + + if (pdoctsnd_obj->data) + removeSharedData (sdf, &(pdoctsnd_obj->data)); + + if (pdtyp != SYMBOL) { + if (pdoctsnd_obj->data = newSharedData (sdf, argc, sizeof(float), pdtyp)) { + f = (float *) pdoctsnd_obj->data; + copyFloats (f, argv, argc); + } + else { + post("pdoctave_send: allocation of shared memory size %d bytes failed!", + sizeof(float) * argc); + return; + } + } + else { + symptr = atom_getsymbol (argv); + if (pdoctsnd_obj->data = newSharedData (sdf, strlen(symptr->s_name)+1, sizeof(char), pdtyp)) { + c = (char *) pdoctsnd_obj->data; + strcpy (c, symptr->s_name); + } + else { + post("pdoctave_send: allocation of shared memory size %d bytes failed!", + sizeof(char) * (strlen(symptr->s_name)+1)); + return; + } + } + blockForReading (sdf); + freeSharedData (sdf, &(pdoctsnd_obj->data)); + pDOctaveSendBang (pdoctsnd_obj); + sleepUntilReadUnBlocked (sdf,STD_USLEEP_TIME); + unBlockForWriting (sdf); +} + +static void deletePDOctaveSend (PDOctaveSend *pdoctsnd_obj) +{ + removeSharedData (pdoctsnd_obj->sdf, &(pdoctsnd_obj->data)); + removeSharedDataFrame (&(pdoctsnd_obj->sdf)); +} + +void pdoctave_send_setup (void) +{ + pdoctave_send_class = class_new + (gensym("pdoctave_send"), + (t_newmethod) newPDOctaveSend, + (t_method) deletePDOctaveSend, + sizeof (PDOctaveSend), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (pdoctave_send_class, (t_method) pDOctaveSendBang); + class_addanything (pdoctave_send_class, (t_method) pDOctaveSend); + post("pdoctave_send successfully loaded"); +} +#endif + diff --git a/pdoctave_send.h b/pdoctave_send.h new file mode 100644 index 0000000..ad914f2 --- /dev/null +++ b/pdoctave_send.h @@ -0,0 +1,5 @@ +#ifndef __pdoctave_get_h_ +#define __pdoctave_get_h_ +void pdoctave_get_setup (void); +#endif + diff --git a/read_shared_mem.cc b/read_shared_mem.cc new file mode 100644 index 0000000..446ee0f --- /dev/null +++ b/read_shared_mem.cc @@ -0,0 +1,99 @@ +#include <octave/oct.h> + +#include <unistd.h> +#include <string.h> +#include "pdoctave_dataframe.h" + +Matrix writeFloatIntoOctMatrix (int n, int m, float *f) +{ + int i; + int j; + Matrix mtx = Matrix(n,m); + for (j = 0; j < n; j++) + for (i=0; i < m; i++) + mtx(j,i) = (double)*f++; + return mtx; +} + +double writeFloatIntoDouble (float f) +{ + return (double) f; +} + +RowVector writeFloatIntoRowVector (int n, float *f) +{ + RowVector rv = RowVector(n); + int i; + for (i = 0; i<n; i++) + rv(i) = (double) *f++; + return rv; +} + +ColumnVector writeFloatIntoColumnVector (int n, float *f) +{ + ColumnVector cv = ColumnVector(n); + int i; + for (i = 0; i<n; i++) + cv(i) = (double) *f++; + return cv; +} + +DEFUN_DLD (read_shared_mem, args, , "reading and returning a pd-value in octave") +{ + SharedDataFrame *sdf; + void *data; + octave_value convert_result; + int shmem_id = args(0).int_value(); + float *f; + std::string str; + std::string quote_sign = "\""; + + if (shmem_id == -1) { + error("failed to get valid id\n"); + return octave_value(); + } + sdf = getSharedDataFrame (shmem_id); + + if (!sdf) { + error("failed to attach memory!\n"); + return octave_value(); + } + sleepUntilWriteBlocked (sdf,STD_USLEEP_TIME); + sleepUntilReadBlocked (sdf, STD_USLEEP_TIME); + + data = getSharedData (sdf); + if (!data) { + error("failed to attach data!\n"); + freeSharedDataFrame (&sdf); + unBlockForReading (sdf); + return octave_value(); + } + + f = (float*) data; + + switch (getSharedDataType (sdf)) { + case FLOAT: + convert_result = octave_value(writeFloatIntoDouble (*f)); + break; + case LIST: + convert_result = octave_value( + writeFloatIntoRowVector (getSharedDataVecLength(sdf), f)); + break; + case SYMBOL: + str = (std::string) (char *) data; + convert_result = octave_value(quote_sign+str+quote_sign); + break; + case MATRIX: + convert_result = octave_value(writeFloatIntoOctMatrix ((int)f[0],(int)f[1],f+2)); + break; + case UNKNOWN: + error("unknown pdoctave type"); + convert_result = octave_value (); + } + unBlockForReading (sdf); + removeSharedData (sdf, &data); + freeSharedDataFrame (&sdf); + return (convert_result); +} + + @@ -0,0 +1,10 @@ +#include <octave/oct.h> + +#include <string.h> +DEFUN_DLD (test, args, , "reading and returning a pd-value in octave") +{ + puts("eval(a+b)\n"); + return octave_value (); +} + + diff --git a/test_pdoctave.pd b/test_pdoctave.pd new file mode 100644 index 0000000..48c6c26 --- /dev/null +++ b/test_pdoctave.pd @@ -0,0 +1,80 @@ +#N canvas 0 0 1027 680 10; +#X obj 199 138 print; +#X msg 219 112 hallo; +#X msg 192 254 list 1 2 3 4 5; +#X msg 265 212 matrix 2 2 1 2 3 4; +#X msg 179 213 2; +#X msg 338 264 symbol halo; +#X floatatom 139 255 5 0 0 0 - - -; +#X msg 244 176 float 2; +#X symbolatom 341 297 10 0 0 0 - - -; +#X obj 354 121 mtx_ones 4 7; +#X obj 389 77 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 138 50 pdoctave; +#X obj 185 291 pdoctave_send a; +#X obj 137 346 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 246 481 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 251 500 pdoctave_command b=[1:5 \; 1 \, 2 \, 3 \, 4 \, 0]; +#X obj 144 575 pdoctave_get a; +#X obj 134 552 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 146 606 print; +#X obj 449 97 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 383 152 mtx_egg 30 15; +#X obj 354 434 mtx_ones; +#X msg 371 410 12; +#X floatatom 436 398 5 0 0 0 - - -; +#X obj 429 416 pp set; +#X obj 114 404 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 123 430 pdoctave_command mesh(a); +#X obj 602 292 mtx_ones 1; +#X floatatom 610 241 5 0 0 0 - - -; +#X obj 615 266 pack f 1; +#X obj 529 194 mtx_rand; +#X floatatom 596 122 5 0 0 0 - - -; +#X obj 192 378 pdoctave_command b=repmat(a \, 1 \, 2); +#X obj 593 546 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 475 316 bang; +#X msg 516 304 clear; +#X obj 522 561 pp set; +#X msg 516 592 ab; +#X obj 749 601 print; +#X obj 515 331 entry 500 200 grey90 black; +#X obj 621 542 pdoctave_command b = [1 \, 2 \, 3 \; 3 4 5]; +#X connect 1 0 0 0; +#X connect 2 0 12 0; +#X connect 3 0 12 0; +#X connect 4 0 12 0; +#X connect 5 0 12 0; +#X connect 6 0 12 0; +#X connect 7 0 12 0; +#X connect 8 0 12 0; +#X connect 9 0 12 0; +#X connect 10 0 9 0; +#X connect 13 0 32 0; +#X connect 14 0 15 0; +#X connect 16 0 18 0; +#X connect 17 0 16 0; +#X connect 19 0 20 0; +#X connect 20 0 12 0; +#X connect 21 0 12 0; +#X connect 22 0 21 0; +#X connect 23 0 24 0; +#X connect 24 0 22 0; +#X connect 25 0 26 0; +#X connect 27 0 12 0; +#X connect 28 0 29 0; +#X connect 29 0 27 0; +#X connect 30 0 12 0; +#X connect 31 0 30 0; +#X connect 33 0 40 0; +#X connect 34 0 39 0; +#X connect 35 0 39 0; +#X connect 36 0 37 0; +#X connect 39 0 40 0; diff --git a/write_shared_mem.cc b/write_shared_mem.cc new file mode 100644 index 0000000..2149e91 --- /dev/null +++ b/write_shared_mem.cc @@ -0,0 +1,105 @@ +#include <octave/oct.h> + +#include <unistd.h> +#include <string.h> +#include "pdoctave_dataframe.h" + +DatTyp classifyOctPDType (octave_value res) +{ + DatTyp pdtyp; + if (res.is_real_scalar()) + pdtyp = FLOAT; + else if (res.is_real_matrix()) + pdtyp = MATRIX; + else if (res.is_string()) + pdtyp = SYMBOL; + else + pdtyp = UNKNOWN; +} + +void writeOctMatrixIntoFloat (Matrix mtx, float *f) +{ + int n = mtx.rows(); + int m = mtx.columns(); + int i; + int j; + + *f++ = n; + *f++ = m; + + for (j = 0; j < m; j++) + for (i=0; i < n; i++) + *f++ = (float) mtx(i,j); +} + +void writeOctScalarIntoFloat (double d, float *f) +{ + *f = (float) d; +} +void writeOctStringIntoString (char *s, char *c) +{ + strcpy (s,c); +} + + +DEFUN_DLD (write_shared_mem, args, , "returning an octave value to pd-value") +{ + SharedDataFrame *sdf; + int size; + void *data; + DatTyp pdtype; + int shmem_id = args(1).int_value(); + + if (shmem_id == -1) { + error("failed to get valid id\n"); + return octave_value(); + } + sdf = getSharedDataFrame (shmem_id); + + if (!sdf) { + error("failed to attach memory!\n"); + return octave_value(); + } + + sleepUntilWriteBlocked (sdf,STD_USLEEP_TIME); + + if (args(0).is_string()) { + pdtype = SYMBOL; + } + else if (args(0).is_real_matrix()) { + pdtype = MATRIX; + size = args(0).columns() * args(0).rows()+2; + if (data = newSharedData (sdf, size, sizeof(float),pdtype)) { + writeOctMatrixIntoFloat (args(0).matrix_value(), (float *) data); + } + else { + error("failed to get new data memory!"); + unBlockForWriting (sdf); + freeSharedDataFrame (&sdf); + return octave_value(); + } + } + else if (args(0).is_real_scalar()) { + pdtype = FLOAT; + if (data = newSharedData (sdf, 1, sizeof(float), pdtype)) { + writeOctScalarIntoFloat(args(0).scalar_value(), (float *) data); + } + else { + error("failed to get new data memory!"); + unBlockForWriting (sdf); + freeSharedDataFrame (&sdf); + return octave_value(); + } + } + else + std::cout << " no mehtod for argument conversion" << std::endl; + + unBlockForWriting (sdf); + + freeSharedData (sdf, &data); + freeSharedDataFrame (&sdf); + + return octave_value(); +} + + |