aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Knight <q@1bpm.net>2021-08-16 02:56:49 +0100
committerRichard Knight <q@1bpm.net>2021-08-16 02:56:49 +0100
commit2e854bcb40d535957b589ad02e3f280e00b47865 (patch)
tree8fe2abbc86130af2d2ff74bbce943a68f2ec4c6d /src
downloadcsound-datacore-2e854bcb40d535957b589ad02e3f280e00b47865.tar.gz
csound-datacore-2e854bcb40d535957b589ad02e3f280e00b47865.tar.bz2
csound-datacore-2e854bcb40d535957b589ad02e3f280e00b47865.zip
pre strip down
Diffstat (limited to 'src')
-rw-r--r--src/maketable.cpp40
-rw-r--r--src/opcodes.cpp770
-rw-r--r--src/pmparser.cpp196
3 files changed, 1006 insertions, 0 deletions
diff --git a/src/maketable.cpp b/src/maketable.cpp
new file mode 100644
index 0000000..511f838
--- /dev/null
+++ b/src/maketable.cpp
@@ -0,0 +1,40 @@
+#include <plugin.h>
+#include "maketable.hpp"
+
+int maketable(csnd::Csound* csound, int size, FUNC **tablep, int channels) {
+ EVTBLK* evt;
+ MYFLT* pf;
+
+ evt = (EVTBLK*) csound->malloc(sizeof(EVTBLK));
+ evt->opcod = 'f';
+ evt->strarg = NULL;
+ evt->pcnt = 5;
+ pf = &evt->p[0];
+ pf[0] = FL(0);
+ pf[1] = FL(0);
+ pf[2] = evt->p2orig = FL(0);
+ pf[3] = evt->p3orig = -size;
+ pf[4] = FL(2); // gen number
+ pf[5] = FL(0);
+ int n = csound->get_csound()->hfgens(csound->get_csound(), tablep, evt, 1);
+ csound->free(evt);
+ if (UNLIKELY(n != 0)) {
+ return NOTOK;
+ }
+
+ FUNC* table = *tablep;
+
+ table->soundend = size;
+ table->nchanls = channels;
+ table->flenfrms = size;
+ table->gen01args.sample_rate = csound->sr();
+ table->cpscvt = 0;
+ table->cvtbas = LOFACT; // * csound->sr() * csound->get_csound()->onedsr;
+ table->loopmode1 = 0;
+ table->loopmode2 = 0;
+ table->begin1 = 0;
+ table->end1 = size;
+ table->begin2 = 0;
+ table->end2 = size;
+ return OK;
+} \ No newline at end of file
diff --git a/src/opcodes.cpp b/src/opcodes.cpp
new file mode 100644
index 0000000..4e1265c
--- /dev/null
+++ b/src/opcodes.cpp
@@ -0,0 +1,770 @@
+#include "pmparser.h"
+#include "maketable.hpp"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <plugin.h>
+#include <functional>
+#include <vector>
+#include <sys/mman.h>
+
+#ifdef USE_X11
+#include <X11/Xlib.h>
+#include <X11/X.h>
+#include <X11/Xutil.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#define PROC_DIR "/proc/"
+
+
+
+struct mempsname : csnd::Plugin<1, 1> {
+ static constexpr char const *otypes = "S";
+ static constexpr char const *itypes = "i";
+ int init() {
+ int pid = inargs[0];
+ char* path = (char*) csound->malloc(sizeof(char) * PATH_MAX);
+ sprintf(path, "%s%d/comm", PROC_DIR, pid);
+
+ FILE* f = fopen(path, "r");
+ char* buffer = (char*) csound->malloc(sizeof(char) * 1024);
+ size_t size = fread(buffer, sizeof(char), 1024, f);
+
+
+ fclose(f);
+ STRINGDAT &opath = outargs.str_data(0);
+ opath.size = strlen(buffer);
+ opath.data = buffer;
+
+ csound->free(path);
+ return OK;
+ }
+};
+
+
+struct memps : csnd::Plugin<1, 0> {
+ static constexpr char const *otypes = "i[]";
+ static constexpr char const *itypes = "";
+
+ int init() {
+
+ int* processes = (int*) csound->malloc(sizeof(int) * 1000);
+ int processnum = 0;
+ if (!getPIDs(processes, &processnum)) {
+ return csound->init_error("Cannot read proc directory");
+ }
+
+ csnd::Vector<MYFLT> &out = outargs.vector_data<MYFLT>(0);
+ out.init(csound, processnum);
+
+ for (int i = 0; i < processnum; i++) {
+ out[i] = (MYFLT) processes[i];
+ }
+ csound->free(processes);
+ return OK;
+ }
+
+ bool isNumeric(char* input) {
+ char* p;
+ strtol(input, &p, 10);
+ return *p == 0;
+ }
+
+ bool getPIDs(int* processes, int* processnum) {
+ uid_t thisUser = getuid();
+ DIR* dir = opendir(PROC_DIR);
+
+ struct dirent* de = NULL;
+ if (dir == NULL) {
+ //return false; // TODO breaks csound, why??
+ }
+ char* path = (char*) csound->malloc(sizeof(char) * PATH_MAX);
+ while (NULL != (de = readdir(dir))) {
+ if (de->d_type == DT_DIR) {
+ if (isNumeric(de->d_name)) {
+
+ struct stat fileInfo;
+ strcpy(path, PROC_DIR);
+ strcat(path, de->d_name);
+ if (stat(path, &fileInfo) == 0) {
+ if (fileInfo.st_uid == thisUser) {
+ (*processnum)++;
+ *processes = (int)atoi(de->d_name);
+ processes++;
+ }
+ }
+ }
+ }
+ }
+ csound->free(path);
+ return true;
+ }
+
+};
+
+
+#ifdef USE_X11
+struct winson : csnd::Plugin<1, 1> {
+ static constexpr char const *otypes = "a";
+ static constexpr char const *itypes = "i";
+ Display* display;
+ Window root;
+ int width;
+ int height;
+ MYFLT* buffer;
+ int buffer_size;
+ int buffer_read_position;
+ int buffer_write_position;
+
+ int init() {
+ display = XOpenDisplay(NULL);
+ //root = DefaultRootWindow(display);
+ root = 0x2200004;
+ XWindowAttributes gwa;
+ XGetWindowAttributes(display, root, &gwa);
+
+ width = gwa.width;
+ height = gwa.height;
+ buffer_size = width * height;
+ buffer = (MYFLT*) csound->malloc(sizeof(MYFLT) * buffer_size);
+ buffer_read_position = 0;
+ buffer_write_position = 0;
+ refill_buffer();
+ return OK;
+ }
+
+ int refill_buffer() {
+ buffer_write_position = 0;
+ XImage* image = XGetImage(display, root, 0, 0, width, height, AllPlanes, ZPixmap);
+ for (int x = 0; x < width; x++) {
+ for (int y=0; y < height; y++) {
+ buffer[buffer_write_position] = ((MYFLT) XGetPixel(image,x,y)) / 16777215;
+ buffer_write_position++;
+ }
+ }
+ return OK;
+ }
+
+ int aperf() {
+ for (int i = 0; i < nsmps; i++) {
+ outargs(0)[i] = buffer[buffer_read_position];
+ if (LIKELY(buffer_read_position + 1 < buffer_size)) {
+ buffer_read_position++;
+ } else {
+ refill_buffer();
+ buffer_read_position = 0;
+ }
+ }
+
+ return OK;
+
+ }
+};
+#endif
+
+
+class MemLocation {
+public:
+ unsigned long start;
+ unsigned long length;
+ unsigned long* content; // for mmap test..
+ MemLocation(unsigned long start, unsigned long length) {
+ this->start = start;
+ this->length = length;
+ }
+};
+
+
+class MemParser {
+private:
+ csnd::Csound* csound;
+ int fd_mem;
+ int pid;
+ bool skip_zero;
+ int buffer_write_position;
+ std::vector<MemLocation*> locations;
+
+ /*
+ void iterate_memory(std::function<void (unsigned long, unsigned long)> func) {
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+ procmaps_struct* maps_tmp = NULL;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ func((unsigned long) maps_tmp->addr_start, (unsigned long) maps_tmp->length);
+ }
+ }
+ pmparser_free(csound, maps);
+ }
+ */
+
+ bool parsed;
+ void parse_memory() {
+ locations.clear();
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+ procmaps_struct* maps_tmp = NULL;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ locations.push_back(
+ new MemLocation(
+ (unsigned long) maps_tmp->addr_start,
+ (unsigned long) maps_tmp->length
+ )
+ );
+ std::cout << (unsigned long) maps_tmp->addr_start << "-" << (unsigned long) maps_tmp->length << "\n";
+ }
+ }
+ pmparser_free(csound, maps);
+ parsed = true;
+ }
+
+ // this idea ends up with more mem locations than expected, whytf? vector malloc not right with csound???
+ void iterate_memory_step(std::function<bool (long, MYFLT)> func) {
+ if (!parsed) parse_memory();
+ long i;
+ MYFLT val; int x = 0;
+ unsigned long* lbuffer = NULL;
+ std::cout << "sz=" << locations.size() << "\n";
+ for (auto &location : locations) {
+ lbuffer = (unsigned long*) csound->malloc(sizeof(unsigned long) * location->length);
+ lseek(fd_mem, location->start, SEEK_SET);
+ read(fd_mem, lbuffer, location->length);
+ std::cout << (unsigned long) location->start << "-" << (unsigned long) location->length << "\n";
+ for (i = 0; i < location->length; i++) {
+ val = ((MYFLT) lbuffer[i]) / ULONG_MAX;
+ if (!skip_zero || (skip_zero && val > 0)) {
+ if (!(func(i, val))) goto complete;
+ }
+
+ }
+
+ if (lbuffer != NULL) {
+ csound->free(lbuffer); // causes segfault, WHY???????????
+ lbuffer = NULL;
+ }
+
+ }
+ complete:
+ if (lbuffer != NULL) {
+ csound->free(lbuffer); // causes segfault, WHY???????????
+ lbuffer = NULL;
+ }
+
+ }
+
+ // func arguments: index and value ; return false to stop iteration, true to continue
+ void Xiterate_memory_step(std::function<bool (long, MYFLT)> func) {
+ MYFLT val;
+ unsigned long* lbuffer = NULL;
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+ procmaps_struct* maps_tmp = NULL;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ unsigned long start = (unsigned long) maps_tmp->addr_start;
+ unsigned long length = (unsigned long) maps_tmp->length;
+ lbuffer = (unsigned long*) csound->malloc(sizeof(unsigned long) * length);
+ lseek(fd_mem, start, SEEK_SET);
+ read(fd_mem, lbuffer, length);
+ for (long i = 0; i < length; i++) {
+ val = ((MYFLT) lbuffer[i]) / ULONG_MAX;
+ if (!skip_zero || (skip_zero && val > 0)) {
+ if (!(func(i, val))) goto complete;
+ }
+ }
+
+ if (lbuffer != NULL) {
+ //csound->free(lbuffer); // causes segfault, WHY???????????
+ //lbuffer = NULL;
+ }
+
+ }
+ }
+ complete:
+ if (lbuffer != NULL) {
+ csound->free(lbuffer); // causes segfault, WHY???????????
+ lbuffer = NULL;
+ }
+ pmparser_free(csound, maps);
+ }
+
+public:
+ long total_size;
+ MYFLT* buffer;
+ int buffer_size;
+
+ MemParser(csnd::Csound* csound, int pid, bool skip_zero) {
+ this->csound = csound;
+ this->skip_zero = skip_zero;
+ this->pid = pid;
+ parsed = false;
+ total_size = 0;
+ buffer = NULL;
+ buffer_size = 0;
+ buffer_write_position = 0;
+ char* mem_path = (char*) csound->malloc(sizeof(char) * 50);
+ sprintf(mem_path, "/proc/%d/mem", pid);
+ fd_mem = open(mem_path, O_RDWR);
+ csound->free(mem_path);
+ }
+
+ ~MemParser() {
+ close(fd_mem);
+ if (buffer != NULL) {
+ csound->free(buffer);
+ }
+ }
+
+ void allocate_buffer(int buffer_size) {
+ buffer = (MYFLT*) csound->malloc(sizeof(MYFLT) * buffer_size);
+ this->buffer_size = buffer_size;
+ }
+
+ long get_size() {
+ total_size = 0;
+ iterate_memory_step(
+ [&](long index, MYFLT val) {
+ total_size ++;
+ return true;
+ }
+ );
+ return total_size;
+ }
+
+
+ int fill_buffer(MYFLT offset) {
+ if (total_size == 0) {
+ total_size = get_size();
+ }
+ buffer_write_position = 0;
+ if (offset > 1) offset = 1;
+ long offset_position = total_size * offset;
+ /*if (UNLIKELY(offset_position > total_size - (buffer_size + 1))) {
+ offset_position = total_size - (buffer_size + 1);
+ }*/
+ bool active;
+
+ iterate_memory_step(
+ [&](long index, MYFLT val) {
+ if (index < offset_position) return true;
+ //std::cout << index << "-" << offset_position << "\n";
+ buffer[buffer_write_position] = val;
+ if (buffer_write_position < buffer_size) {
+ buffer_write_position ++;
+ } else {
+ buffer_write_position = 0;
+ return false;
+ }
+ return true;
+ }
+ );
+ }
+
+ void fill_table(FUNC* table, long length) {
+ long write_index = 0;
+ bool active = true;
+
+ iterate_memory_step(
+ [&](long index, MYFLT val) {
+ table->ftable[write_index] = val;
+ write_index ++;
+ return true;
+ }
+ );
+ }
+
+};
+
+
+// ifn mem2tab ipid, iskipzero=0
+struct mem2tab : csnd::Plugin<1, 2> {
+ static constexpr char const *otypes = "i";
+ static constexpr char const *itypes = "io";
+
+ int init() {
+ FUNC *table;
+ MemParser* mp = new MemParser(csound, (int)inargs[0], (inargs[1] > 0));
+
+ long length = mp->get_size();
+ if ((maketable(csound, (int)length, &table, 1)) != OK) {
+ return csound->init_error("Cannot create ftable");
+ }
+ mp->fill_table(table, (int)length);
+ outargs[0] = table->fno;
+ return OK;
+ }
+};
+
+
+// read memory from a given pid as audio
+// aout memson ipid, koffset, kbuffer_readratio, ibuffersize=441000, iskipzero=0
+struct memson : csnd::Plugin<1, 5> {
+ static constexpr char const *otypes = "a";
+ static constexpr char const *itypes = "ikkjo";
+ MemParser* mp;
+ int buffer_read_position;
+ MYFLT last_offset;
+
+ int init() {
+ mp = new MemParser(csound, (int)inargs[0], (inargs[4] > 0));
+ mp->allocate_buffer((inargs[2] == -1)? 441000: (int) inargs[3]);
+
+ buffer_read_position = 0;
+ last_offset = inargs[1];
+ mp->fill_buffer(last_offset);
+
+ return OK;
+ }
+
+ int aperf() {
+ for (int i = 0; i < nsmps; i++) {
+ outargs(0)[i] = mp->buffer[buffer_read_position];
+ if (LIKELY(buffer_read_position < mp->buffer_size*inargs[2])) {
+ buffer_read_position++;
+ } else {
+ buffer_read_position = 0;
+ }
+ }
+ if (inargs[1] != last_offset) {
+ last_offset = inargs[1];
+ mp->fill_buffer(last_offset);
+ }
+
+ return OK;
+
+ }
+
+
+};
+
+
+
+
+
+typedef struct mmap {
+ unsigned long start;
+ unsigned long length;
+} _mmap;
+
+
+// read memory from a given pid as audio
+// aout memson2 ipid, koffset, kbufsize [, iunsafe]
+// where kbufsize is 0 to 1 and koffset is 0 to 1
+struct memson2 : csnd::Plugin<1, 4> {
+ static constexpr char const *otypes = "a";
+ static constexpr char const *itypes = "ikkj";
+ int pid;
+ int buffer_read_position;
+ int buffer_write_position;
+ int buffer_size;
+ int max_buffer_size;
+ unsigned long total_locations;
+ MYFLT* buffer;
+ MYFLT last_buffer_ratio;
+ MYFLT last_offset;
+ char* mem_path;
+ bool unsafe;
+
+ int init() {
+ max_buffer_size = 441000;
+ buffer_size = (int) (inargs[2] * max_buffer_size);
+ last_buffer_ratio = inargs[2];
+ last_offset = inargs[1];
+ unsafe = (((int)inargs[3]) == 1);
+ csound->plugin_deinit(this);
+ pid = (int) inargs[0];
+ buffer = (MYFLT*) csound->malloc(sizeof(MYFLT) * max_buffer_size);
+ mem_path = (char*) csound->malloc(sizeof(char) * 50);
+ sprintf(mem_path, "/proc/%d/mem", pid);
+
+ buffer_read_position = 0;
+ buffer_write_position = 0;
+ total_locations = max_locations();
+ refill_buffer(inargs[1], true);
+
+ return OK;
+ }
+
+ int deinit() {
+ csound->free(mem_path);
+ return OK;
+ }
+
+ unsigned long max_locations() {
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+ int fd_mem = open(mem_path, O_RDWR);
+ unsigned long len = 0;
+ procmaps_struct* maps_tmp = NULL;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ len += maps_tmp->length;
+ }
+ }
+ pmparser_free(csound, maps);
+ close(fd_mem);
+ return len;
+ }
+
+ int read_mem(int fd_mem, unsigned long start, unsigned long length) {
+ length = length; // 4; // ??????????????????????????????????????????????????????
+ // lbuffer as unsigned char
+ // https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux
+ unsigned long* lbuffer = (unsigned long*) csound->malloc(sizeof(unsigned long) * length);
+ lseek(fd_mem, start, SEEK_SET);
+ read(fd_mem, lbuffer, length);
+
+ int i;
+ for (i = 0; i < length; i++) {
+ //std::cout << "a " << buffer_write_position << "x " << buffer_size << "\n";
+ MYFLT val = ((MYFLT)lbuffer[i]) / ULONG_MAX;
+ buffer[buffer_write_position] = val;
+ if (buffer_write_position + 1 < buffer_size) {
+ buffer_write_position++;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+
+ int refill_buffer(MYFLT offset, bool first) {
+ buffer_write_position = 0;
+ if (offset > 1) offset = 1;
+ long offset_position = total_locations * offset;
+ if (UNLIKELY(offset_position > total_locations - (buffer_size + 1))) {
+ offset_position = total_locations - (buffer_size + 1);
+ }
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+
+ if (maps == NULL) {
+ //csound->message("cannot open maps");
+ return NOTOK; //csound->perf_error("cannot open maps", this->insdshead);
+ }
+
+ int fd_mem = open(mem_path, O_RDWR);
+ if (fd_mem == -1) {
+ //csound->message("cannot open memory");
+ return NOTOK;
+ }
+
+ long position = 0;
+ unsigned long aof = 0;
+ procmaps_struct* maps_tmp = NULL;
+ int res = 0;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ if (position >= offset_position) {
+ aof = position - offset_position; // not quite right, length needs sorting
+ res = read_mem(fd_mem, ((unsigned long) maps_tmp->addr_start) + aof, (unsigned long) maps_tmp->length);
+ }
+ position += maps_tmp->length;
+ if (res == 1) {
+ break;
+ }
+ }
+ }
+ pmparser_free(csound, maps);
+ close(fd_mem);
+ return OK;
+ }
+
+ int aperf() {
+ if (last_offset != inargs[1] || last_buffer_ratio != inargs[2]) {
+ last_offset = inargs[1];
+ last_buffer_ratio = inargs[2];
+ buffer_size = (int) (inargs[2] * max_buffer_size);
+ refill_buffer(inargs[1], false);
+ buffer_read_position = 0;
+
+ }
+ for (int i = 0; i < nsmps; i++) {
+ outargs(0)[i] = buffer[buffer_read_position];
+ if (LIKELY(buffer_read_position + 1 < buffer_size)) {
+ buffer_read_position++;
+ } else {
+ refill_buffer(inargs[1], false);
+ buffer_read_position = 0;
+ }
+ }
+
+ return OK;
+
+ }
+
+
+};
+
+
+
+
+
+// read memory from a given pid as audio
+struct memson3 : csnd::Plugin<1, 3> {
+ static constexpr char const *otypes = "a";
+ static constexpr char const *itypes = "ikk";
+ int pid;
+ int buffer_read_position;
+ int buffer_write_position;
+ int buffer_size;
+ int max_buffer_size;
+ unsigned long total_locations;
+ MYFLT* buffer;
+ unsigned char* lbuffer;
+ MYFLT last_buffer_ratio;
+ MYFLT last_offset;
+ char* mem_path;
+
+ int init() {
+ max_buffer_size = 441000;
+ buffer_size = (int) (inargs[2] * max_buffer_size);
+ last_buffer_ratio = inargs[2];
+ last_offset = inargs[1];
+ csound->plugin_deinit(this);
+ pid = (int) inargs[0];
+ buffer = (MYFLT*) csound->malloc(sizeof(MYFLT) * max_buffer_size);
+ lbuffer = (unsigned char*) csound->malloc(sizeof(unsigned char) * max_buffer_size);
+ mem_path = (char*) csound->malloc(sizeof(char) * 50);
+ sprintf(mem_path, "/proc/%d/mem", pid);
+
+ buffer_read_position = 0;
+ buffer_write_position = 0;
+ total_locations = max_locations();
+ refill_buffer(inargs[1]);
+
+ return OK;
+ }
+
+ int deinit() {
+ csound->free(mem_path);
+ return OK;
+ }
+
+ unsigned long max_locations() {
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+ int fd_mem = open(mem_path, O_RDWR);
+ unsigned long len = 0;
+ procmaps_struct* maps_tmp = NULL;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ len += maps_tmp->length;
+ }
+ }
+ pmparser_free(csound, maps);
+ close(fd_mem);
+ return len;
+ }
+
+ int read_mem(int fd_mem, unsigned long start, unsigned long length) {
+ length = length; // 4; // ??????????????????????????????????????????????????????
+ // lbuffer as unsigned char
+ // https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux
+ lseek(fd_mem, start, SEEK_SET);
+ read(fd_mem, lbuffer, length);
+
+ int i;
+ for (i = 0; i < length; i++) {
+ //std::cout << "a " << buffer_write_position << "x " << buffer_size << "\n";
+ MYFLT val = ((MYFLT)lbuffer[i]) / UCHAR_MAX;
+ buffer[buffer_write_position] = val;
+ if (buffer_write_position + 1 < buffer_size) {
+ buffer_write_position++;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+
+ int refill_buffer(MYFLT offset) {
+ buffer_write_position = 0;
+ if (offset > 1) offset = 1;
+ long offset_position = total_locations * offset;
+ if (UNLIKELY(offset_position > total_locations - (buffer_size + 1))) {
+ offset_position = total_locations - (buffer_size + 1);
+ }
+ procmaps_iterator* maps = pmparser_parse(csound, pid);
+
+ if (maps == NULL) {
+ //csound->message("cannot open maps");
+ return NOTOK; //csound->perf_error("cannot open maps", this->insdshead);
+ }
+
+ int fd_mem = open(mem_path, O_RDWR);
+ if (fd_mem == -1) {
+ //csound->message("cannot open memory");
+ return NOTOK;
+ }
+
+ long position = 0;
+ unsigned long aof = 0;
+ procmaps_struct* maps_tmp = NULL;
+ int res = 0;
+ while ((maps_tmp = pmparser_next(maps)) != NULL) {
+ if (maps_tmp->is_r && maps_tmp->is_w) {
+ if (position >= offset_position) {
+ aof = position - offset_position; // not quite right, length needs sorting
+ res = read_mem(fd_mem, ((unsigned long) maps_tmp->addr_start) + aof, (unsigned long) maps_tmp->length);
+ }
+ position += maps_tmp->length;
+ if (res == 1) {
+ break;
+ }
+ }
+ }
+ pmparser_free(csound, maps);
+ close(fd_mem);
+ return OK;
+ }
+
+ int aperf() {
+ if (last_offset != inargs[1] || last_buffer_ratio != inargs[2]) {
+ last_offset = inargs[1];
+ last_buffer_ratio = inargs[2];
+ buffer_size = (int) (inargs[2] * max_buffer_size);
+ refill_buffer(inargs[1]);
+ buffer_read_position = 0;
+
+ }
+ for (int i = 0; i < nsmps; i++) {
+ outargs(0)[i] = buffer[buffer_read_position];
+ if (LIKELY(buffer_read_position + 1 < buffer_size)) {
+ buffer_read_position++;
+ } else {
+ refill_buffer(inargs[1]);
+ buffer_read_position = 0;
+ }
+ }
+
+ return OK;
+
+ }
+
+
+};
+
+
+
+#include <modload.h>
+
+void csnd::on_load(csnd::Csound *csound) {
+ csnd::plugin<memson>(csound, "memson", csnd::thread::ia);
+ csnd::plugin<memson2>(csound, "memson2", csnd::thread::ia);
+ csnd::plugin<memson3>(csound, "memson3", csnd::thread::ia);
+ csnd::plugin<memps>(csound, "memps", csnd::thread::i);
+ csnd::plugin<mempsname>(csound, "mempsname", csnd::thread::i);
+ csnd::plugin<mem2tab>(csound, "mem2tab", csnd::thread::i);
+
+
+#ifdef USE_X11
+ csnd::plugin<winson>(csound, "winson", csnd::thread::ia);
+#endif
+}
+
diff --git a/src/pmparser.cpp b/src/pmparser.cpp
new file mode 100644
index 0000000..e7be9ba
--- /dev/null
+++ b/src/pmparser.cpp
@@ -0,0 +1,196 @@
+/*
+ @Author : ouadimjamal@gmail.com
+ @date : December 2015
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation. No representations are made about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+*/
+
+#include "pmparser.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <plugin.h>
+
+
+
+
+procmaps_iterator* pmparser_parse(csnd::Csound* csound, int pid){
+ procmaps_iterator* maps_it = (procmaps_iterator*) csound->malloc(sizeof(procmaps_iterator));
+ char maps_path[500];
+ if(pid>=0 ){
+ sprintf(maps_path,"/proc/%d/maps",pid);
+ }else{
+ sprintf(maps_path,"/proc/self/maps");
+ }
+ FILE* file=fopen(maps_path,"r");
+ if(!file){
+ fprintf(stderr,"pmparser : cannot open the memory maps, %s\n",strerror(errno));
+ return NULL;
+ }
+ int ind=0;char buf[PROCMAPS_LINE_MAX_LENGTH];
+ int c;
+ procmaps_struct* list_maps=NULL;
+ procmaps_struct* tmp;
+ procmaps_struct* current_node=list_maps;
+ char addr1[20],addr2[20], perm[8], offset[20], dev[10],inode[30],pathname[PATH_MAX];
+ while( !feof(file) ){
+ fgets(buf,PROCMAPS_LINE_MAX_LENGTH,file);
+ //allocate a node
+ tmp=(procmaps_struct*)csound->malloc(sizeof(procmaps_struct));
+ //fill the node
+ _pmparser_split_line(buf,addr1,addr2,perm,offset, dev,inode,pathname);
+ //printf("#%s",buf);
+ //printf("%s-%s %s %s %s %s\t%s\n",addr1,addr2,perm,offset,dev,inode,pathname);
+ //addr_start & addr_end
+ unsigned long l_addr_start;
+ sscanf(addr1,"%lx",(long unsigned *)&tmp->addr_start );
+ sscanf(addr2,"%lx",(long unsigned *)&tmp->addr_end );
+ //size
+ tmp->length=(unsigned long)(tmp->addr_end-tmp->addr_start);
+ //perm
+ strcpy(tmp->perm,perm);
+ tmp->is_r=(perm[0]=='r');
+ tmp->is_w=(perm[1]=='w');
+ tmp->is_x=(perm[2]=='x');
+ tmp->is_p=(perm[3]=='p');
+
+ //offset
+ sscanf(offset,"%lx",&tmp->offset );
+ //device
+ strcpy(tmp->dev,dev);
+ //inode
+ tmp->inode=atoi(inode);
+ //pathname
+ strcpy(tmp->pathname,pathname);
+ tmp->next=NULL;
+ //attach the node
+ if(ind==0){
+ list_maps=tmp;
+ list_maps->next=NULL;
+ current_node=list_maps;
+ }
+ current_node->next=tmp;
+ current_node=tmp;
+ ind++;
+ //printf("%s",buf);
+ }
+
+ //close file
+ fclose(file);
+
+
+ //g_last_head=list_maps;
+ maps_it->head = list_maps;
+ maps_it->current = list_maps;
+ return maps_it;
+}
+
+
+procmaps_struct* pmparser_next(procmaps_iterator* p_procmaps_it){
+ if(p_procmaps_it->current == NULL)
+ return NULL;
+ procmaps_struct* p_current = p_procmaps_it->current;
+ p_procmaps_it->current = p_procmaps_it->current->next;
+ return p_current;
+ /*
+ if(g_current==NULL){
+ g_current=g_last_head;
+ }else
+ g_current=g_current->next;
+
+ return g_current;
+ */
+}
+
+
+
+void pmparser_free(csnd::Csound* csound, procmaps_iterator* p_procmaps_it){
+ procmaps_struct* maps_list = p_procmaps_it->head;
+ if(maps_list==NULL) return ;
+ procmaps_struct* act=maps_list;
+ procmaps_struct* nxt=act->next;
+ while(act!=NULL){
+ csound->free(act);
+ act=nxt;
+ if(nxt!=NULL)
+ nxt=nxt->next;
+ }
+
+}
+
+
+void _pmparser_split_line(
+ char*buf,char*addr1,char*addr2,
+ char*perm,char* offset,char* device,char*inode,
+ char* pathname){
+ //
+ int orig=0;
+ int i=0;
+ //addr1
+ while(buf[i]!='-'){
+ addr1[i-orig]=buf[i];
+ i++;
+ }
+ addr1[i]='\0';
+ i++;
+ //addr2
+ orig=i;
+ while(buf[i]!='\t' && buf[i]!=' '){
+ addr2[i-orig]=buf[i];
+ i++;
+ }
+ addr2[i-orig]='\0';
+
+ //perm
+ while(buf[i]=='\t' || buf[i]==' ')
+ i++;
+ orig=i;
+ while(buf[i]!='\t' && buf[i]!=' '){
+ perm[i-orig]=buf[i];
+ i++;
+ }
+ perm[i-orig]='\0';
+ //offset
+ while(buf[i]=='\t' || buf[i]==' ')
+ i++;
+ orig=i;
+ while(buf[i]!='\t' && buf[i]!=' '){
+ offset[i-orig]=buf[i];
+ i++;
+ }
+ offset[i-orig]='\0';
+ //dev
+ while(buf[i]=='\t' || buf[i]==' ')
+ i++;
+ orig=i;
+ while(buf[i]!='\t' && buf[i]!=' '){
+ device[i-orig]=buf[i];
+ i++;
+ }
+ device[i-orig]='\0';
+ //inode
+ while(buf[i]=='\t' || buf[i]==' ')
+ i++;
+ orig=i;
+ while(buf[i]!='\t' && buf[i]!=' '){
+ inode[i-orig]=buf[i];
+ i++;
+ }
+ inode[i-orig]='\0';
+ //pathname
+ pathname[0]='\0';
+ while(buf[i]=='\t' || buf[i]==' ')
+ i++;
+ orig=i;
+ while(buf[i]!='\t' && buf[i]!=' ' && buf[i]!='\n'){
+ pathname[i-orig]=buf[i];
+ i++;
+ }
+ pathname[i-orig]='\0';
+
+}