[PD-cvs] externals/iem/pdoctave pdoctave.c, NONE, 1.1 pdoctave.h, NONE, 1.1 pdoctave.pd, NONE, 1.1 pdoctave_command.c, NONE, 1.1 pdoctave_command.h, NONE, 1.1 pdoctave_dataframe.c, NONE, 1.1 pdoctave_dataframe.h, NONE, 1.1 pdoctave_datatypes.h, NONE, 1.1 pdoctave_get.c, NONE, 1.1 pdoctave_get.h, NONE, 1.1 pdoctave_send.c, NONE, 1.1 pdoctave_send.h, NONE, 1.1 read_shared_mem.cc, NONE, 1.1 test.cc, NONE, 1.1 test_pdoctave.pd, NONE, 1.1 write_shared_mem.cc, NONE, 1.1

Franz Zotter fzotter at users.sourceforge.net
Wed Feb 22 13:48:18 CET 2006


Update of /cvsroot/pure-data/externals/iem/pdoctave
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8561

Added Files:
	pdoctave.c pdoctave.h pdoctave.pd pdoctave_command.c 
	pdoctave_command.h pdoctave_dataframe.c pdoctave_dataframe.h 
	pdoctave_datatypes.h pdoctave_get.c pdoctave_get.h 
	pdoctave_send.c pdoctave_send.h read_shared_mem.cc test.cc 
	test_pdoctave.pd write_shared_mem.cc 
Log Message:
These is the beginning of a try to connect the pd to octave. Especially when using the iemmatrix features in pd, this feature becomes sensible. On the whole it shall enable the user to use the command line parser of octave. 

The take-over strategy is bad at this starting point. No threading, no practical data transmission. 
Perhaps the common work on it can help. (Franz)



--- NEW FILE: read_shared_mem.cc ---
#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);
}



--- NEW FILE: pdoctave_dataframe.h ---
#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

--- NEW FILE: pdoctave_get.c ---
#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


--- NEW FILE: test.cc ---
#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 ();
}



--- NEW FILE: pdoctave_datatypes.h ---
typedef enum {
   MATRIX,
   FLOAT,
   LIST,
   SYMBOL,
   UNKNOWN
} DatTyp;

--- NEW FILE: pdoctave_get.h ---
#ifndef __pdoctave_send_h_
#define __pdoctave_send_h_
void pdoctave_send_setup (void);
#endif


--- NEW FILE: pdoctave_dataframe.c ---
#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);
      }
	 
   }
}
      

--- NEW FILE: pdoctave_command.h ---
#ifndef __pdoctave_command_h_
#define __pdoctave_command_h_
void pdoctave_command_setup (void);
#endif


--- NEW FILE: pdoctave_send.c ---
#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


--- NEW FILE: pdoctave.h ---
// pdoctave functions

// functions return -1 when they fail (= octave object is not instanciated in pd)

int getPDOctaveInstances ();
int writeToOctaveStdIN (const char *cmd);

--- NEW FILE: pdoctave_command.c ---
#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


--- NEW FILE: pdoctave_send.h ---
#ifndef __pdoctave_get_h_
#define __pdoctave_get_h_
void pdoctave_get_setup (void);
#endif


--- NEW FILE: pdoctave.c ---
#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

--- NEW FILE: write_shared_mem.cc ---
#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();
}



--- NEW FILE: pdoctave.pd ---
#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;

--- NEW FILE: test_pdoctave.pd ---
#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;





More information about the Pd-cvs mailing list