From 3c37fbee81a6858c98a272bddb6b1c520883cd93 Mon Sep 17 00:00:00 2001 From: xiphmont Date: Tue, 11 Sep 2007 19:57:15 +0000 Subject: [PATCH] Broad front of work in progress: Begin new objective function mapping work Extend locking model to directional/multistage Begin abstracting plane rendering out of 2d Begin collapsing all panels into single panel type git-svn-id: http://svn.xiph.org/trunk@13782 0101bb08-14d6-0310-b084-bc0e0c8e3800 --- sushivision/Makefile | 9 +- sushivision/example_fractal.c | 14 +- sushivision/gtksucks.c | 87 +++-------- sushivision/internal.h | 42 +++++- sushivision/main.c | 337 ++++++++++++++++++++++++++++++++++++++---- sushivision/objective.c | 215 +++++++++++---------------- sushivision/objective.h | 31 ++-- sushivision/panel-2d.c | 45 +++--- sushivision/panel-2d.h | 53 ++++--- sushivision/panel.c | 2 +- sushivision/slider.c | 20 ++- sushivision/sushimacro.h | 144 ------------------ sushivision/sushivision.h | 58 +------- sushivision/tokens.c | 22 +++ 14 files changed, 562 insertions(+), 517 deletions(-) delete mode 100644 sushivision/sushimacro.h diff --git a/sushivision/Makefile b/sushivision/Makefile index c77bb6098..2672d9312 100644 --- a/sushivision/Makefile +++ b/sushivision/Makefile @@ -24,16 +24,15 @@ MANDIR = $(PREFIX)/man SOCFLAGS = -fPIC SOLDFLAGS = -shared -nostdlib -Wl,-soname="lib$(NAME).so.$(MAJOR)" -SRC = main.c scale.c plot.c slider.c slice.c spinner.c panel.c panel-1d.c panel-2d.c \ - panel-xy.c mapping.c dimension.c function.c objective.c undo.c gtksucks.c xml.c \ +SRC = main.c scale.c plot.c slider.c slice.c spinner.c objective.c panel.c panel-2d.c \ + mapping.c dimension.c function.c undo.c gtksucks.c xml.c \ tokens.c example_fractal.c example_discrete.c example_chirp.c example_spirograph.c INC = sushivision.h sushimacro.h MAN = EXAMPLES = sushivision_fractal #sushivision_discrete sushivision_chirp EX_OBJ = example_fractal.o #example_discrete.o example_chirp.o example_spirograph.o -OBJ = main.o scale.o plot.o slider.o slice.o spinner.c panel.o panel-1d.o panel-2d.o \ - panel-xy.o mapping.o dimension.o function.o objective.o undo.o gtksucks.o xml.o \ - tokens.c +OBJ = main.o scale.o plot.o slider.o slice.o spinner.c objective.o panel.o panel-2d.o \ + mapping.o dimension.o function.o undo.o gtksucks.o xml.o tokens.c LIBS = -lpthread -ldl CAIROVER = >= 1.4.1 GTKVER = >= 2.10.0 diff --git a/sushivision/example_fractal.c b/sushivision/example_fractal.c index 43ed3fbe4..2f6120671 100644 --- a/sushivision/example_fractal.c +++ b/sushivision/example_fractal.c @@ -78,23 +78,15 @@ int main(int argc, char *argv[]){ "100000:one hundred thousand"); sv_dim_set_value(100); - sv_func_t *f = sv_func_new(0, 2, fractal_objective, 0); - - sv_obj_new("outer", - (sv_func_t *[]){f}, - (int []){0}, - "Y"); + sv_obj_new("outer",fractal_objective,"rc,ic,rz,iz,it", "Z,*"); sv_obj_make_scale("0, .001, .01, .1, 1.0"); - sv_obj_new("inner", - (sv_func_t *[]){f}, - (int []){1}, - "Y"); + sv_obj_new("inner",fractal_objective,"rc,ic,rz,iz,it", "*,Z"); sv_obj_make_scale("0, .001, .01, .1, 1.0"); sv_panel_new_2d(0,"Mandel/Julia Fractal", "inner, outer", - "rc,ic,rz,iz,it", + "rc(X,Y), ic(X,Y), rz(X,Y), iz(X,Y), it", 0); sv_go(); diff --git a/sushivision/gtksucks.c b/sushivision/gtksucks.c index ecb13372a..630ef54f9 100644 --- a/sushivision/gtksucks.c +++ b/sushivision/gtksucks.c @@ -37,14 +37,14 @@ behaviors. */ /**********************************************************************/ -/* fixup number 1: insensitive widgets (except children of viewports, - a special case) eat mouse events. This doesn't seem like a big - deal, but if you're implementing a right-click context menu, this - means you cannot pop a menu if the user was unlucky enough to have - right-clicked over an insensitive widget. Wrap the widget - sensitivity setting method to also also set/unset the - GDK_BUTTON_PRESS_MASK on a widget; when insensitive, this will - remove its ability to silently swallow mouse events. */ +/* Insensitive widgets (except children of viewports, a special case) + eat mouse events. This doesn't seem like a big deal, but if you're + implementing a right-click context menu, this means you cannot pop + a menu if the user was unlucky enough to have right-clicked over an + insensitive widget. Wrap the widget sensitivity setting method to + also also set/unset the GDK_BUTTON_PRESS_MASK on a widget; when + insensitive, this will remove its ability to silently swallow mouse + events. */ /* Note that this only works after the widget is realized, as realization will clobber the event mask */ @@ -127,16 +127,15 @@ void _gtk_widget_remove_events (GtkWidget *widget, } /**********************************************************************/ -/* fixup number 2: Buttons (and their subclasses) don't do anything - with mousebutton3, but they swallow the events anyway preventing - them from cascading. The 'supported' way of implementing a - context-sensitive right-click menu is to recursively bind a new - handler to each and every button on a toplevel. This is mad - whack. The below 'fixes' buttons at the class level by ramming a - new button press handler into the GtkButtonClass structure (and, - unfortunately, button subclasses as their classes have also already - initialized and made a copy of the Button's class structure and - handlers */ +/* Buttons (and their subclasses) don't do anything with mousebutton3, + but they swallow the events anyway preventing them from cascading. + The 'supported' way of implementing a context-sensitive right-click + menu is to recursively bind a new handler to each and every button + on a toplevel. This is mad whack. The below 'fixes' buttons at + the class level by ramming a new button press handler into the + GtkButtonClass structure (and, unfortunately, button subclasses as + their classes have also already initialized and made a copy of the + Button's class structure and handlers */ static gboolean _gtk_button_button_press_new (GtkWidget *widget, GdkEventButton *event){ @@ -197,58 +196,6 @@ void _gtk_button3_fixup(){ } /**********************************************************************/ -/* fixup number 3: GDK uses whatever default mutex type offered by the - system, and this usually means non-recursive ('fast') mutextes. - The problem with this is that gdk_threads_enter() and - gdk_threads_leave() cannot be used in any call originating from the - main loop, but are required in calls from idle handlers and other - threads. In effect we would need seperate identical versions of - each widget method, one locked, one unlocked, depending on where - the call originated. Eliminate this problem by installing a - recursive mutex. */ - -static pthread_mutex_t gdkm; -static pthread_mutexattr_t gdkma; -static int depth = 0; -static int firstunder = 0; - -static void recursive_gdk_lock(void){ - pthread_mutex_lock(&gdkm); - depth++; -} - -static void recursive_gdk_unlock(void){ - depth--; - if(depth<0){ - if(!firstunder){ // annoying detail of gtk locking; in apps that - // don't normally use threads, onr does not lock before entering - // mainloop; in apps that do thread, the mainloop must be - // locked. We can't tell which situation was in place before - // setting up our own threading, so allow one refcount error - // which we assume was the unlocked mainloop of a normally - // unthreaded gtk app. - firstunder++; - depth=0; - }else{ - fprintf(stderr,"Internal locking error; refcount < 0. Dumping core for debugging\n"); - abort(); - } - }else - pthread_mutex_unlock(&gdkm); -} - -void _gtk_mutex_fixup(){ - pthread_mutexattr_init(&gdkma); - pthread_mutexattr_settype(&gdkma,PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&gdkm,&gdkma); - gdk_threads_set_lock_functions(recursive_gdk_lock,recursive_gdk_unlock); -} - -pthread_mutex_t *_gtk_get_mutex(void){ - return &gdkm; -} - -/**********************************************************************/ /* Not really a fixup; generate menus that declare what the keyboard shortcuts are */ diff --git a/sushivision/internal.h b/sushivision/internal.h index cc8aef674..1144c5bb6 100644 --- a/sushivision/internal.h +++ b/sushivision/internal.h @@ -29,6 +29,38 @@ typedef struct _sv_undo _sv_undo_t; #include #include "sushivision.h" +/* locking *****************************************************/ + +// strict mutex acquisation ordering: +// gdk -> panel -> objective -> dimension -> scale +// functions below check/enforce + +extern void _sv_gdk_lock_i(const char *func, int line); +extern void _sv_gdk_unlock_i(const char *func, int line); +extern void _sv_panel_lock_i(const char *func, int line); +extern void _sv_panel_unlock_i(const char *func, int line); +extern void _sv_objective_lock_i(const char *func, int line); +extern void _sv_objective_unlock_i(const char *func, int line); +extern void _sv_dimension_lock_i(const char *func, int line); +extern void _sv_dimension_unlock_i(const char *func, int line); +extern void _sv_scale_lock_i(const char *func, int line); +extern void _sv_scale_unlock_i(const char *func, int line); + +#define gdk_lock() _sv_gdk_lock_i(__FUNCTION__,__LINE__); +#define gdk_unlock() _sv_gdk_lock_i(__FUNCTION__,__LINE__); + +#define panel_lock() _sv_panel_lock_i(__FUNCTION__,__LINE__); +#define panel_unlock() _sv_panel_lock_i(__FUNCTION__,__LINE__); + +#define obj_lock() _sv_objective_lock_i(__FUNCTION__,__LINE__); +#define obj_unlock() _sv_objective_lock_i(__FUNCTION__,__LINE__); + +#define dim_lock() _sv_dimension_lock_i(__FUNCTION__,__LINE__); +#define dim_unlock() _sv_dimension_lock_i(__FUNCTION__,__LINE__); + +#define scale_lock() _sv_scale_lock_i(__FUNCTION__,__LINE__); +#define scale_unlock() _sv_scale_lock_i(__FUNCTION__,__LINE__); + typedef struct { char *s; double v; @@ -47,6 +79,8 @@ typedef struct { _sv_token **list; } _sv_tokenlist; +/* tokenization and API argument parsing *****************************/ + // name string // labelname name[:string] // displayvalue number[:string] @@ -70,12 +104,14 @@ extern _sv_token *_sv_tokenize_valuelist(char *in); extern _sv_token *_sv_tokenize_nameparam(char *in); extern _sv_token *_sv_tokenize_declparam(char *in); extern _sv_tokenlist *_sv_tokenize_namelist(char *in); +extern _sv_tokenlist *_sv_tokenize_noparamlist(char *in); extern void _sv_tokenval_free(_sv_tokenval *t); extern void _sv_token_free(_sv_token *t); extern void _sv_tokenlist_free(_sv_tokenlist *l); extern char *_sv_tokenize_escape(char *a); -// used to glue numeric settings to semantic labels for menus/save files + +/* used to glue numeric settings to semantic labels for menus/save files **/ typedef struct _sv_propmap _sv_propmap_t; struct _sv_propmap { char *left; @@ -246,8 +282,6 @@ extern char *_sv_filename; extern char *_sv_dirname; extern char *_sv_cwdname; -extern int _sv_functions; -extern sv_func_t **_sv_function_list; extern int _sv_dimensions; extern sv_dim_t **_sv_dimension_list; extern int _sv_objectives; @@ -261,3 +295,5 @@ extern _sv_undo_t **_sv_undo_stack; extern pthread_key_t _sv_dim_key; extern pthread_key_t _sv_obj_key; +extern sv_obj_t *_sv_obj(char *name); +extern sv_dim_t *_sv_dim(char *name); diff --git a/sushivision/main.c b/sushivision/main.c index 3f538c9eb..7571e2456 100644 --- a/sushivision/main.c +++ b/sushivision/main.c @@ -39,18 +39,285 @@ #include "internal.h" #include "sushi-gtkrc.h" -static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t mc = PTHREAD_COND_INITIALIZER; +// strict mutex acquisation ordering: gdk -> panel -> objective -> dimension -> scale +typedef struct { + int holding_gdk; + + int holding_panel; + const char *func_panel; + int line_panel; + + int holding_obj; + const char *func_obj; + int line_obj; + + int holding_dim; + const char *func_dim; + int line_dim; + + int holding_scale; + const char *func_scale; + int line_scale; + +} mutexcheck; + +static pthread_mutex_t panel_m = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t obj_m = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t dim_m = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t scale_m = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t _sv_mutexcheck_key; + +/**********************************************************************/ +/* GDK uses whatever default mutex type offered by the system, and + this usually means non-recursive ('fast') mutextes. The problem + with this is that gdk_threads_enter() and gdk_threads_leave() + cannot be used in any call originating from the main loop, but are + required in calls from idle handlers and other threads. In effect + we would need seperate identical versions of each widget method, + one locked, one unlocked, depending on where the call originated. + Eliminate this problem by installing a recursive mutex. */ + +static pthread_mutex_t gdk_m; +static pthread_mutexattr_t gdk_ma; +static int gdk_firstunder = 0; + +void _sv_gdk_lock_i(const char *func, int line){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + const char *m=NULL; + const char *f=NULL; + int l=-1; + + if(!check){ + check = calloc(1,sizeof(*check)); + pthread_setspecific(_sv_mutexcheck_key, (void *)check); + } + + if(check->holding_panel){ m="panel"; f=check->func_panel; l=check->line_panel; } + if(check->holding_obj){ m="objective"; f=check->func_obj; l=check->line_obj; } + if(check->holding_dim){ m="dimension"; f=check->func_dim; l=check->line_dim; } + if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; } + + if(f){ + if(func) + fprintf(stderr,"sushivision: Out of order locking error.\n" + "\tTrying to acquire gdk lock in %s line %d,\n" + "\t%s lock already held from %s line %d.\n", + func,line,m,f,l); + else + fprintf(stderr,"sushivision: Out of order locking error.\n" + "\tTrying to acquire gdk lock, %s lock already held\n" + "\tfrom %s line %d.\n", + m,f,l); + } + + pthread_mutex_lock(&gdk_m); + check->holding_gdk++; + +} + +void _sv_gdk_unlock_i(const char *func, int line){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + + if(!check){ + if(!gdk_firstunder){ // annoying detail of gtk locking; in apps that + // don't normally use threads, one does not lock before entering + // mainloop; in apps that do thread, the mainloop must be + // locked. We can't tell which situation was in place before + // setting up our own threading, so allow one refcount error + // which we assume was the unlocked mainloop of a normally + // unthreaded gtk app. + check = calloc(1,sizeof(*check)); + pthread_setspecific(_sv_mutexcheck_key, (void *)check); + gdk_firstunder++; + }else{ + if(func) + fprintf(stderr,"sushivision: locking error.\n" + "\tTrying to unlock gdk when no gdk lock held\n" + "\tin %s line %d.\n", + func,line); + else + fprintf(stderr,"sushivision: locking error.\n" + "\tTrying to unlock gdk when no gdk lock held.\n"); + + } + }else{ + check->holding_gdk--; + pthread_mutex_unlock(&gdk_m); + } +} + +// dumbed down version to pass into gdk +static void replacement_gdk_lock(void){ + _sv_gdk_lock_i(NULL,-1); +} + +static void replacement_gdk_unlock(void){ + _sv_gdk_unlock_i(NULL,-1); +} + +static mutexcheck *lockcheck(){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + if(!check){ + check = calloc(1,sizeof(*check)); + pthread_setspecific(_sv_mutexcheck_key, (void *)check); + } + return check; +} + +void _sv_panel_lock_i(const char *func, int line){ + mutexcheck *check = lockcheck(); + const char *m=NULL, *f=NULL; + int l=-1; + + if(check->holding_obj){ m="objective"; f=check->func_obj; l=check->line_obj; } + if(check->holding_dim){ m="dimension"; f=check->func_dim; l=check->line_dim; } + if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; } + + if(f) + fprintf(stderr,"sushivision: Out of order locking error.\n" + "\tTrying to acquire panel lock in %s line %d,\n" + "\t%s lock already held from %s line %d.\n", + func,line,m,f,l); + + pthread_mutex_lock(&panel_m); + check->holding_panel++; + check->func_panel = func; + check->line_panel = line; + +} + +void _sv_panel_unlock_i(const char *func, int line){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + + if(!check || check->holding_panel<1){ + fprintf(stderr,"sushivision: locking error.\n" + "\tTrying to unlock panel when no panel lock held\n" + "\tin %s line %d.\n", + func,line); + }else{ + + check->holding_panel--; + check->func_panel = "(unknown)"; + check->line_panel = -1; + pthread_mutex_unlock(&panel_m); + + } +} + +void _sv_objective_lock_i(const char *func, int line){ + mutexcheck *check = lockcheck(); + const char *m=NULL, *f=NULL; + int l=-1; + + if(check->holding_dim){ m="dimension"; f=check->func_dim; l=check->line_dim; } + if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; } + + if(f) + fprintf(stderr,"sushivision: Out of order locking error.\n" + "\tTrying to acquire objective lock in %s line %d,\n" + "\t%s lock already held from %s line %d.\n", + func,line,m,f,l); + + pthread_mutex_lock(&obj_m); + check->holding_obj++; + check->func_obj = func; + check->line_obj = line; + +} + +void _sv_objective_unlock_i(const char *func, int line){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + + if(!check || check->holding_obj<1){ + fprintf(stderr,"sushivision: locking error.\n" + "\tTrying to unlock objective when no objective lock held\n" + "\tin %s line %d.\n", + func,line); + }else{ + + check->holding_obj--; + check->func_obj = "(unknown)"; + check->line_obj = -1; + pthread_mutex_unlock(&obj_m); + + } +} + +void _sv_dimension_lock_i(const char *func, int line){ + mutexcheck *check = lockcheck(); + const char *m=NULL, *f=NULL; + int l=-1; + + if(check->holding_scale){ m="scale"; f=check->func_scale; l=check->line_scale; } + + if(f) + fprintf(stderr,"sushivision: Out of order locking error.\n" + "\tTrying to acquire dimension lock in %s line %d,\n" + "\t%s lock already held from %s line %d.\n", + func,line,m,f,l); + + pthread_mutex_lock(&dim_m); + check->holding_dim++; + check->func_dim = func; + check->line_dim = line; + +} + +void _sv_dimension_unlock_i(const char *func, int line){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + + if(!check || check->holding_dim<1){ + fprintf(stderr,"sushivision: locking error.\n" + "\tTrying to unlock dimension when no dimension lock held\n" + "\tin %s line %d.\n", + func,line); + }else{ + + check->holding_dim--; + check->func_dim = "(unknown)"; + check->line_dim = -1; + pthread_mutex_unlock(&dim_m); + + } +} + +void _sv_scale_lock_i(const char *func, int line){ + mutexcheck *check = lockcheck(); + + pthread_mutex_lock(&scale_m); + check->holding_scale++; + check->func_scale = func; + check->line_scale = line; + +} + +void _sv_scale_unlock_i(const char *func, int line){ + mutexcheck *check = pthread_getspecific(_sv_mutexcheck_key); + + if(!check || check->holding_scale<1){ + fprintf(stderr,"sushivision: locking error.\n" + "\tTrying to unlock scale when no scale lock held\n" + "\tin %s line %d.\n", + func,line); + }else{ + + check->holding_scale--; + check->func_scale = "(unknown)"; + check->line_scale = -1; + pthread_mutex_unlock(&scale_m); + + } +} + +// mutex condm is only for protecting the condvar +static pthread_mutex_t worker_condm = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t worker_cond = PTHREAD_COND_INITIALIZER; sig_atomic_t _sv_exiting=0; static int wake_pending = 0; static int num_threads; -int _sv_functions=0; -sv_func_t **_sv_function_list=NULL; int _sv_dimensions=0; sv_dim_t **_sv_dimension_list=NULL; -int _sv_objectives=0; -sv_obj_t **_sv_objective_list=NULL; int _sv_panels=0; sv_panel_t **_sv_panel_list=NULL; int _sv_undo_level=0; @@ -61,22 +328,22 @@ pthread_key_t _sv_dim_key; pthread_key_t _sv_obj_key; void _sv_wake_workers(){ - pthread_mutex_lock(&m); + pthread_mutex_lock(&worker_condm); wake_pending = num_threads; - pthread_cond_broadcast(&mc); - pthread_mutex_unlock(&m); + pthread_cond_broadcast(&worker_cond); + pthread_mutex_unlock(&worker_condm); } void _sv_clean_exit(){ _sv_exiting = 1; _sv_wake_workers(); - gdk_threads_enter(); + gdk_lock(); if(!gtk_main_iteration_do(FALSE)) // side effect: returns true if // there are no main loops active gtk_main_quit(); - gdk_threads_leave(); - + + gdk_unlock(); } static int num_proccies(){ @@ -117,7 +384,7 @@ static void *worker_thread(void *dummy){ if(_sv_exiting)break; // pending remap work? - gdk_threads_enter(); + gdk_lock(); if(p && p->private && p->private->realized && p->private->graph){ // pending computation work? @@ -153,21 +420,21 @@ static void *worker_thread(void *dummy){ !p->private->map_active) _sv_spinner_set_idle(p->private->spinner); } - gdk_threads_leave (); + gdk_unlock (); } if(flag==1)continue; } // nothing to do, wait - pthread_mutex_lock(&m); + pthread_mutex_lock(&worker_condm); if(!wake_pending) - pthread_cond_wait(&mc,&m); + pthread_cond_wait(&worker_cond,&worker_condm); else wake_pending--; - pthread_mutex_unlock(&m); + pthread_mutex_unlock(&worker_condm); } - pthread_mutex_unlock(&m); + pthread_mutex_unlock(&worker_condm); return 0; } @@ -192,16 +459,16 @@ char *_sv_cwdname = NULL; static void *event_thread(void *dummy){ - gdk_threads_enter(); + gdk_lock(); gtk_main (); - gdk_threads_leave(); + gdk_unlock(); // in case there's another mainloop in the main app - gdk_threads_enter(); + gdk_lock(); if(!gtk_main_iteration_do(FALSE)) // side effect: returns true if // there are no main loops active gtk_main_quit(); - gdk_threads_leave(); + gdk_unlock(); return 0; } @@ -209,11 +476,20 @@ static void *event_thread(void *dummy){ /* externally visible interface */ int sv_init(){ int ret=0; + if((ret=pthread_key_create(&_sv_mutexcheck_key,NULL))) + return ret; if((ret=pthread_key_create(&_sv_dim_key,NULL))) - return ret; - + return ret; + if((ret=pthread_key_create(&_sv_obj_key,NULL))) + return ret; + num_threads = num_proccies(); - _gtk_mutex_fixup(); + + pthread_mutexattr_init(&gdk_ma); + pthread_mutexattr_settype(&gdk_ma,PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&gdk_m,&gdk_ma); + gdk_threads_set_lock_functions(replacement_gdk_lock, + replacement_gdk_unlock); gtk_init (NULL,NULL); return 0; @@ -221,9 +497,9 @@ int sv_init(){ int sv_join(){ while(!_sv_exiting){ - pthread_mutex_lock(&m); - pthread_cond_wait(&mc,&m); - pthread_mutex_unlock(&m); + pthread_mutex_lock(&worker_condm); + pthread_cond_wait(&worker_cond,&worker_condm); + pthread_mutex_unlock(&worker_condm); } return 0; } @@ -235,7 +511,7 @@ int sv_go(){ gtk_rc_parse_string(gtkrc_string()); gtk_rc_add_default_file("sushi-gtkrc"); - gdk_threads_enter(); + gdk_lock(); _sv_realize_all(); _gtk_button3_fixup(); @@ -293,9 +569,10 @@ int sv_go(){ //signal(SIGINT,_sv_clean_exit); //signal(SIGSEGV,_sv_clean_exit); + gdk_unlock(); + { pthread_t dummy; - gdk_threads_leave(); return pthread_create(&dummy, NULL, &event_thread,NULL); } } diff --git a/sushivision/objective.c b/sushivision/objective.c index 1cf13ae85..de226cc53 100644 --- a/sushivision/objective.c +++ b/sushivision/objective.c @@ -25,22 +25,30 @@ #include #include "internal.h" -sv_obj_t *sv_obj_new(char *name, - sv_func_t **function_map, - int *function_output_map, - char *output_type_map){ - - sv_obj_t *o; - sv_obj_internal_t *p; - int i; - int outputs = strlen(output_type_map); +int _sv_objectives=0; +sv_obj_t **_sv_objective_list=NULL; + +static char *objective_axismap[]={ + "X","Y","Z" +}; + +#define map_axes ((int)sizeof(objective_axismap)/(int)sizeof(*objective_axismap)) + +int sv_obj_new(char *name, + void(*function)(double *,double *), + char *input_map, + char *output_map){ + + sv_obj_t *o = NULL; + int i,j; int number; _sv_token *decl = _sv_tokenize_declparam(name); + _sv_tokenlist *in = NULL; + _sv_tokenlist *out = NULL; if(!decl){ fprintf(stderr,"sushivision: Unable to parse objective declaration \"%s\".\n",name); - errno = -EINVAL; - return NULL; + goto err; } if(_sv_objectives == 0){ @@ -57,133 +65,82 @@ sv_obj_t *sv_obj_new(char *name, } o = _sv_objective_list[number] = calloc(1, sizeof(**_sv_objective_list)); - p = o->private = calloc(1,sizeof(*o->private)); - - /* sanity check the maps */ - for(i=0;i=function_map[i]->outputs){ - fprintf(stderr,"Objectve %d (\"%s\"): function %d does not have an output %d.\n", - number,name,function_map[i]->number,function_output_map[i]); - errno = -EINVAL; - return NULL; + o->name = strdup(decl->name); + o->legend = strdup(decl->label); + o->number = number; + o->function = function; + + /* parse and sanity check the maps */ + in = _sv_tokenize_noparamlist(input_map); + out = _sv_tokenize_noparamlist(output_map); + + /* input dimensions */ + if(!in){ + fprintf(stderr,"sushivision: Unable to parse objective \"%s\" dimenension list \"%s\".\n", + o->name,input_map); + goto err; + } + + o->inputs = in->n; + o->input_dims = calloc(in->n,sizeof(*o->input_dims)); + for(i=0;in;i++){ + sv_dim_t *id = sv_dim(in->list[i]->name); + if(!id){ + fprintf(stderr,"sushivision: Dimension \"%s\" does not exist in declaration of objective \"%s\".\n", + in->list[i]->name,o->name); + goto err; } - switch(output_type_map[i]){ - case 'X': - if(p->x_func){ - fprintf(stderr,"Objective %d: More than one X dimension specified.\n", - number); - errno = -EINVAL; - return NULL; - } - p->x_fout = function_output_map[i]; - p->x_func = (sv_func_t *)function_map[i]; - break; - - case 'Y': - if(p->y_func){ - fprintf(stderr,"Objective %d: More than one Y dimension specified.\n", - number); - errno = -EINVAL; - return NULL; - } - p->y_fout = function_output_map[i]; - p->y_func = (sv_func_t *)function_map[i]; - break; - - case 'Z': - if(p->z_func){ - fprintf(stderr,"Objective %d: More than one Z dimension specified.\n", - number); - errno = -EINVAL; - return NULL; - } - p->z_fout = function_output_map[i]; - p->z_func = (sv_func_t *)function_map[i]; - break; - - case 'M': - if(p->m_func){ - fprintf(stderr,"Objective %d: More than one magnitude [M] dimension specified.\n", - number); - errno = -EINVAL; - return NULL; - } - p->m_fout = function_output_map[i]; - p->m_func = (sv_func_t *)function_map[i]; - break; - - case 'E': - if(p->e2_func){ - fprintf(stderr,"Objective %d: More than two error [E] dimensions specified.\n", - number); - errno = -EINVAL; - return NULL; - } - if(p->e1_func){ - p->e2_fout = function_output_map[i]; - p->e2_func = (sv_func_t *)function_map[i]; - }else{ - p->e1_fout = function_output_map[i]; - p->e1_func = (sv_func_t *)function_map[i]; - } - break; - - case 'P': - if(p->p2_func){ - fprintf(stderr,"Objective %d: More than two phase [P] dimensions specified.\n", - number); - errno = -EINVAL; - return NULL; + o->input_dims[i] = id; + } + + /* output axes */ + o->outputs = out->n; + o->output_axes = malloc(map_axes * sizeof(*o->output_axes)); + for(i=0;ioutput_axes[i]=-1; + + for(i=0;in;i++){ + char *s = out->list[i]->name; + if(!s || !strcasecmp(s,"*")){ + // output unused by objective + // do nothing + }else{ + for(j=0;joutput_axes[j] != -1){ + fprintf(stderr,"sushivision: Objective \"%s\" declares multiple %s axis outputs.\n", + o->name,objective_axismap[j]); + goto err; + } + o->output_axes[j] = i; + } } - if(p->p1_func){ - p->p2_fout = function_output_map[i]; - p->p2_func = (sv_func_t *)function_map[i]; - }else{ - p->p1_fout = function_output_map[i]; - p->p1_func = (sv_func_t *)function_map[i]; + if(j==map_axes){ + fprintf(stderr,"sushivision: No such output axis \"%s\" in declaration of objective \"%s\"\n", + s,o->name); } - break; - - default: - fprintf(stderr,"Objective %d: '%c' is an usupported output type.\n", - number,output_type_map[i]); - errno = -EINVAL; - return NULL; } } - o->number = number; - o->name = strdup(decl->name); - o->legend = strdup(decl->label); - o->output_types = strdup(output_type_map); - o->type = SV_OBJ_BASIC; - o->outputs = outputs; - - /* copy in the maps */ - o->function_map = malloc(outputs * sizeof(*o->function_map)); - o->output_map = malloc(outputs * sizeof(*o->output_map)); - memcpy(o->output_map,function_output_map,outputs * sizeof(*o->output_map)); - - for(i=0;ifunction_map[i] = function_map[i]->number; - pthread_setspecific(_sv_obj_key, (void *)o); + _sv_token_free(decl); + _sv_tokenlist_free(in); + _sv_tokenlist_free(out); + + return 0; + + err: + // XXXXX - return o; + return -EINVAL; } // XXXX need to recompute after // XXXX need to add scale cloning to compute to make this safe in callbacks int sv_obj_set_scale(sv_scale_t *scale){ - sv_obj_t *o = sv_obj(0); + sv_obj_t *o = _sv_obj(0); if(o->scale) sv_scale_free(o->scale); // always a deep copy we own @@ -198,7 +155,7 @@ int sv_obj_set_scale(sv_scale_t *scale){ // XXXX need to recompute after // XXXX need to add scale cloning to compute to make this safe in callbacks int sv_obj_make_scale(char *format){ - sv_obj_t *o = sv_obj(0); + sv_obj_t *o = _sv_obj(0); sv_scale_t *scale; int ret; @@ -224,7 +181,7 @@ int sv_obj_make_scale(char *format){ return ret; } -sv_obj_t *sv_obj(char *name){ +sv_obj_t *_sv_obj(char *name){ int i; if(name == NULL || name == 0 || !strcmp(name,"")){ @@ -240,3 +197,9 @@ sv_obj_t *sv_obj(char *name){ } return NULL; } + +int sv_obj(char *name){ + sv_obj_t *o = _sv_obj(name); + if(o)return 0; + return -EINVAL; +} diff --git a/sushivision/objective.h b/sushivision/objective.h index af991dcb4..2b91443c2 100644 --- a/sushivision/objective.h +++ b/sushivision/objective.h @@ -19,23 +19,18 @@ * */ -struct _sv_obj_internal { - sv_func_t *x_func; - sv_func_t *y_func; - sv_func_t *z_func; - sv_func_t *e1_func; - sv_func_t *e2_func; - sv_func_t *p1_func; - sv_func_t *p2_func; - sv_func_t *m_func; +struct _sv_obj { + int number; + char *name; + char *legend; - int x_fout; - int y_fout; - int z_fout; - int e1_fout; - int e2_fout; - int p1_fout; - int p2_fout; - int m_fout; -}; + sv_scale_t *scale; + + void (*function)(double *,double *); + int inputs; + sv_dim_t **input_dims; + int outputs; + int *output_axes; + int flags; +}; diff --git a/sushivision/panel-2d.c b/sushivision/panel-2d.c index 18674aa67..3d1eb2f33 100644 --- a/sushivision/panel-2d.c +++ b/sushivision/panel-2d.c @@ -80,7 +80,7 @@ static void _sv_panel2d_compute_line(sv_panel_t *p, } } - gdk_threads_enter (); + gdk_lock (); if(p->private->plot_serialno == serialno){ for(j=0;jy_obj_num;j++){ int *d = p2->y_map[j] + y*dw; @@ -90,7 +90,7 @@ static void _sv_panel2d_compute_line(sv_panel_t *p, } } - gdk_threads_leave (); + gdk_unlock (); } // call with lock @@ -132,11 +132,6 @@ typedef struct{ double x; double y; double z; - double e1; - double e2; - double p1; - double p2; - double m; } compute_result; // used by the legend code. this lets us get away with having only a mapped display pane @@ -156,7 +151,7 @@ static void _sv_panel2d_compute_point(sv_panel_t *p,sv_obj_t *o, double x, doubl dim_vals[i]=dim->val; } - gdk_threads_leave (); + gdk_unlock (); dim_vals[x_d] = x; dim_vals[y_d] = y; @@ -209,7 +204,7 @@ static void _sv_panel2d_compute_point(sv_panel_t *p,sv_obj_t *o, double x, doubl } } } - gdk_threads_enter (); + gdk_lock (); } @@ -421,7 +416,7 @@ static int _sv_panel2d_resample_render_y_plane_line(sv_panel_t *p, _sv_bythread_ memcpy(data,in_data+ystart*dw,sizeof(data)); - gdk_threads_leave(); + gdk_unlock(); unsigned char *xdelA = c->xdelA; unsigned char *xdelB = c->xdelB; @@ -492,7 +487,7 @@ static int _sv_panel2d_resample_render_y_plane_line(sv_panel_t *p, _sv_bythread_ int data[dw]; memcpy(data,in_data+i*dw,sizeof(data)); - gdk_threads_leave(); + gdk_unlock(); for(j=0;jprivate->plot_serialno || map_serialno != p->private->map_serialno) return -1; @@ -564,7 +559,7 @@ static int _sv_panel2d_render_bg_line(sv_panel_t *p, int plot_serialno, int map_ p2->bg_next_line++; /* gray background checks */ - gdk_threads_leave(); + gdk_unlock(); switch(bgmode){ case SV_BG_WHITE: @@ -584,7 +579,7 @@ static int _sv_panel2d_render_bg_line(sv_panel_t *p, int plot_serialno, int map_ for(j=0;jobjectives;j++){ int o_ynum = p2->y_obj_from_panel[j]; - gdk_threads_enter(); + gdk_lock(); if(plot_serialno != p->private->plot_serialno || map_serialno != p->private->map_serialno) return -1; @@ -596,11 +591,11 @@ static int _sv_panel2d_render_bg_line(sv_panel_t *p, int plot_serialno, int map_ _sv_ucolor_t *rect = p2->y_planes[o_ynum] + i*pw; memcpy(work_pl,rect,sizeof(work_pl)); - gdk_threads_leave(); + gdk_unlock(); for(x=0;xprivate->plot_serialno || map_serialno != p->private->map_serialno) return -1; @@ -1383,9 +1378,9 @@ static int _sv_panel2d_legend_redraw(sv_panel_t *p){ _sv_panel2d_update_legend(p); _sv_panel_clean_legend(p); - gdk_threads_leave(); + gdk_unlock(); _sv_plot_draw_scales(plot); - gdk_threads_enter(); + gdk_lock(); _sv_plot_expose_request(plot); return 1; @@ -1508,9 +1503,9 @@ static int _sv_panel2d_compute(sv_panel_t *p, _sv_panel2d_mark_map_full(p); _sv_panel_dirty_map(p); - gdk_threads_leave (); + gdk_unlock (); _sv_plot_draw_scales(plot); // this should happen outside lock - gdk_threads_enter (); + gdk_lock (); } _sv_map_set_throttle_time(p); // swallow the first 'throttled' remap which would only be a single line; @@ -1554,12 +1549,12 @@ static int _sv_panel2d_compute(sv_panel_t *p, } /* unlock for computation */ - gdk_threads_leave (); + gdk_unlock (); dim_vals[y_d]=_sv_scalespace_value(&sy_i, y); _sv_panel2d_compute_line(p, serialno, dw, y, x_d, sx_i, dim_vals, &c->p2); - gdk_threads_enter (); + gdk_lock (); if(p->private->plot_serialno == serialno){ p->private->plot_complete_count++; @@ -1580,7 +1575,7 @@ static void _sv_panel2d_recompute_callback(void *ptr){ sv_panel_t *p = (sv_panel_t *)ptr; int i; - gdk_threads_enter (); + gdk_lock (); _sv_panel2d_mark_recompute(p); _sv_panel2d_compute(p,NULL); // initial scale setup @@ -1591,7 +1586,7 @@ static void _sv_panel2d_recompute_callback(void *ptr){ for(i=0;idatarect+pw*i, pw, i); - gdk_threads_leave(); + gdk_unlock(); } static void _sv_panel2d_undo_log(_sv_panel_undo_t *u, sv_panel_t *p){ diff --git a/sushivision/panel-2d.h b/sushivision/panel-2d.h index f1a851c55..a7f7cb95b 100644 --- a/sushivision/panel-2d.h +++ b/sushivision/panel-2d.h @@ -19,34 +19,42 @@ * */ +#define PLANE_Z 1 + +union { + _sv_planez_t z; +} _sv_plane_t; + +typedef struct { + // common + int plane_type; + int working; + sv_obj_t *o; + _sv_plane_t *share_next; + _sv_plane_t *share_prev; + + // subtype + float *data; // native data size + int32_t *map; // native data size + _sv_ucolor_t *buffer; // resampled data size; + + unsigned char *line_status; + int progress; +} _sv_planez_t; + typedef struct { GtkWidget *obj_table; GtkWidget *dim_table; - /* only run those functions used by this panel */ - int used_functions; - sv_func_t **used_function_list; - unsigned char *bg_todo; int bg_next_line; int bg_first_line; int bg_last_line; - /**** Y PLANES ******/ - int y_obj_num; - int **y_map; // indirected, dw*dh - _sv_ucolor_t **y_planes; // indirected, dw*dh - unsigned char **y_planetodo; // indirected, dh - int partial_remap; - - int y_next_plane; // which y plane to issue next render - int y_next_line; // incremented when a line is claimed, per plane [0-ph) - - sv_obj_t **y_obj_list; // list of objectives with a y plane - int *y_obj_to_panel; /* maps from position in condensed list to position in full list */ - int *y_obj_from_panel; /* maps from position in full list to position in condensed list */ - int *y_fout_offset; + int planes; + _sv_plane_t **plane_list; + int next_plane; /* cached resampling helpers */ int resample_serialno; @@ -83,10 +91,8 @@ typedef struct { } _sv_panel2d_t; typedef struct { - double *fout; // [function number * outval_number] - - int **y_map; // [y_obj_list[i]][px] - int storage_width; + double *fout; + int fout_size; /* cached resampling helpers; x is here becasue locking overhead would be prohibitive to share between threads */ @@ -96,6 +102,5 @@ typedef struct { int *xnumA; int *xnumB; float xscalemul; - -} _sv_bythread_cache_2d_t; +} _sv_bythread_cache_2d_t; diff --git a/sushivision/panel.c b/sushivision/panel.c index edacc8aa3..d49e3957e 100644 --- a/sushivision/panel.c +++ b/sushivision/panel.c @@ -849,7 +849,7 @@ sv_panel_t * _sv_panel_new(int number, p->objective_list = malloc(p->objectives*sizeof(*p->objective_list)); for(i=0;iobjectives;i++){ char *name = obj_tokens->list[i]->name; - p->objective_list[i].o = sv_obj(name); + p->objective_list[i].o = _sv_obj(name); p->objective_list[i].p = p; } diff --git a/sushivision/slider.c b/sushivision/slider.c index 3b754822d..e5d7787c2 100644 --- a/sushivision/slider.c +++ b/sushivision/slider.c @@ -471,17 +471,21 @@ static double val_to_pixel(_sv_slider_t *s,double v){ double _sv_slider_val_to_del(_sv_slider_t *s,double v){ if(isnan(v))return NAN; - int j; + int j=s->labels-2; int flip = (s->neg? 1: 0); + double del; - for(j=0;jlabels;j++){ - if(((v<=s->label_vals[j+1]) ^ flip) || (j+2)==s->labels){ - double del=(v-s->label_vals[j])/(s->label_vals[j+1]-s->label_vals[j]); - return (j+del)/(s->labels-1); - } + if((v>s->label_vals[j+1]) ^ flip){ + del=(v-s->label_vals[j])/(s->label_vals[j+1]-s->label_vals[j]); + return (j+del)/(s->labels-1); + }else{ + j=0; + while(1) + if((v<=s->label_vals[++j]) ^ flip)break; + --j; + del=(v-s->label_vals[j])/(s->label_vals[j+1]-s->label_vals[j]); + return (j+del)/(s->labels-1); } - - return NAN; } void _sv_slider_expose_slice(_sv_slider_t *s, int slicenum){ diff --git a/sushivision/sushimacro.h b/sushivision/sushimacro.h deleted file mode 100644 index a12efe8eb..000000000 --- a/sushivision/sushimacro.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * sushivision copyright (C) 2006-2007 Monty - * - * sushivision is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * sushivision is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with sushivision; see the file COPYING. If not, write to the - * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -#ifndef _SUSHIMACRO_ -#define _SUSHIMACRO_ - -#include -#include -#include -#include "sushivision.h" - -static sv_instance_t *svm_instance_curr = NULL; -static int svm_instance_number = 0; - -static double *svm_scale_vals_curr = NULL; -static int svm_scale_vsize_curr = 0; -static char **svm_scale_labels_curr = NULL; -static int svm_scale_lsize_curr = 0; - -static sv_dim_t *svm_dim_curr = NULL; -static unsigned svm_scale_flags_curr = 0; -static sv_dim_t **svm_dim_list = NULL; -static int svm_dim_listsize = 0; - -// helpers - -#define svm_scale_check(a, b, c) \ - ( svm_scale_vals_curr ? \ - (fprintf(stderr,"No scale defined for %s %d (\"%s\")\n",#a,(b),c), \ - 1 ): \ - (svm_scale_labels_curr && svm_scale_vsize_curr != svm_scale_lsize_curr ? \ - (fprintf(stderr,"Scale values and labels list size mismatch for %s %d (\"%s\")\n",#a,(b),c), \ - 1 ): \ - (0) )) - -#define svm_dim_check(f) \ - ( !svm_dim_curr ? \ - (fprintf(stderr,"No dimension currently set at %s\n",#f), \ - 1): \ - (0) ) - -#define svm_dim_list_add(d) \ - ( (svm_dim_list && svm_dim_listsize ? \ - (svm_dim_list = realloc(svm_dim_list, sizeof(*svm_dim_list)*(svm_dim_listsize+2))): \ - (svm_dim_list = calloc(2, sizeof(*svm_dim_list)))), \ - svm_dim_list[svm_dim_listsize] = (d) , \ - svm_dim_listsize++) - -#define svm_dim_list_clear() \ - ( (svm_dim_list ? \ - (free(svm_dim_list), \ - svm_dim_list = NULL) : 0), \ - svm_dim_listsize = 0 ) - -// toplevel - -#define svm_new(name) \ - ( svm_instance_curr = sv_new(svm_instance_number, name), \ - svm_instance_number++, \ - svm_instance_curr ) - -#define svm_scale_vals(...) \ - svm_scale_vals_curr = (double []){__VA_ARGS__}; \ - svm_scale_vsize_curr = (sizeof((double []){__VA_ARGS__})/sizeof(double)); - -#define svm_scale_labels(...) \ - svm_scale_labels_curr = (char []){__VA_ARGS__}; \ - svm_scale_lsize_curr = (sizeof((char *[]){__VA_ARGS__})/sizeof(char *)); - -#define svm_scale_flags(number) \ - (svm_scale_flags_curr = (number)) - -#define svm_dim(number, name) \ - ( svm_scale_check(dimension,number,name) ? \ - (svm_dim_curr = NULL ): \ - (svm_dim_curr = sv_dim_new(svm_instance_curr, number, name, 0), \ - sv_dim_make_scale(svm_dim_curr, svm_scale_vsize_curr, svm_scale_vals_curr, svm_scale_labels_curr, svm_scale_flags_curr), \ - svm_scale_vals_curr = NULL, \ - svm_scale_labels_curr = NULL, \ - svm_scale_vsize_curr = 0, \ - svm_scale_lsize_curr = 0, \ - svm_scale_flags_curr = 0, \ - svm_dim_list_add(svm_dim_curr), \ - svm_dim_curr) ) - -#define svm_dim_set(number) \ - ( !svm_instance_curr ? \ - (fprintf(stderr,"No instance currently set while trying to retrieve dimension %d\n",(number)), \ - svm_dim_curr = NULL ): \ - ( number<0 || number >= svm_instance_curr->dimensions ? \ - (fprintf(stderr,"Dimension %d does not exist in instance \"%s\"\n", (number), svm_instance_curr->name), \ - svm_dim_curr = NULL) : \ - (svm_dim_curr = svm_instance_curr->dimension_list[(number)])) ) - -#define svm_dim_discrete(num,den) \ - ( svm_dim_check(svm_dim_curr)? \ - 1 : sv_dim_set_discrete(svm_dim_curr,num,den)) - -#define svm_dim_value(a,b,c) \ - ( svm_dim_check(svm_dim_disabled)? \ - (1) : \ - ( !isnan(a) ? sv_dim_set_value(svm_dim_curr,0,(a)) : 0, \ - !isnan(b) ? sv_dim_set_value(svm_dim_curr,1,(b)) : 0, \ - !isnan(c) ? sv_dim_set_value(svm_dim_curr,2,(c)) : 0, \ - (0))) - -#define svm_dim_list(...) \ - ( svm_dim_list_clear(), \ - svm_dim_listsize = sizeof((sv_dim_t *[]){__VA_ARGS__}) / sizeof(sv_dim_t *), \ - svm_dim_list = calloc(svm_dim_listsize + 1, sizeof(sv_dim_t *)), \ - memcpy(svm_dim_list, (sv_dim_t *[]){__VA_ARGS__}, svm_dim_listsize * sizeof(sv_dim_t *)) ) - -#define svm_obj_simple(num,name,func,map) \ - ( svm_func_list_clear(), \ - svm_func_curr = sv_func(svm_instance_curr, svm_func_curr_num, strlen(map), func, 0), \ - svm_obj_curr = sv_obj_new(svm_obj_curr, num, name, (sv_func_t *[]){svm_func_curr}, \ - (int []){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},map,0), \ - (svm_scale_vals_curr ? \ - (svm_scale_check(objective,number,name) ? \ - (sv_obj_make_scale(svm_obj_curr, svm_scale_vsize_curr, svm_scale_vals_curr, svm_scale_labels_curr, svm_scale_flags_curr)):\ - (0)):0), \ - svm_scale_clear(), \ - svm_obj_curr) - - -#endif diff --git a/sushivision/sushivision.h b/sushivision/sushivision.h index 6ced6c4b7..a12e83289 100644 --- a/sushivision/sushivision.h +++ b/sushivision/sushivision.h @@ -25,15 +25,10 @@ typedef struct sv_scale sv_scale_t; typedef struct sv_panel sv_panel_t; typedef struct sv_dim sv_dim_t; -typedef struct sv_obj sv_obj_t; -typedef struct sv_func sv_func_t; +typedef struct _sv_obj sv_obj_t; typedef struct _sv_scale_internal sv_scale_internal_t; typedef struct _sv_dim_internal sv_dim_internal_t; typedef union _sv_dim_subtype sv_dim_subtype_t; -typedef struct _sv_func_internal sv_func_internal_t; -typedef union _sv_func_subtype sv_func_subtype_t; -typedef struct _sv_obj_internal sv_obj_internal_t; -typedef union _sv_obj_subtype sv_obj_subtype_t; typedef struct _sv_panel_internal sv_panel_internal_t; typedef union _sv_panel_subtype sv_panel_subtype_t; @@ -110,55 +105,14 @@ int sv_dim_set_bracket (double lo, int sv_dim_callback_value (int (*callback)(sv_dim_t *, void*), void *callback_data); -/* functions *****************************************************/ - -enum sv_func_type { SV_FUNC_BASIC }; - -struct sv_func { - int number; - enum sv_func_type type; - int inputs; - int outputs; - - void (*callback)(double *,double *); - unsigned flags; - - sv_func_subtype_t *subtype; - sv_func_internal_t *private; -}; - -sv_func_t *sv_func_new (int number, - int out_vals, - void (*function)(double *,double *), - unsigned flags); - /* objectives ****************************************************/ -enum sv_obj_type { SV_OBJ_BASIC }; - -struct sv_obj { - int number; - char *name; - char *legend; - enum sv_obj_type type; - - sv_scale_t *scale; - int outputs; - int *function_map; - int *output_map; - char *output_types; - unsigned flags; - - sv_obj_subtype_t *subtype; - sv_obj_internal_t *private; -}; - -sv_obj_t *sv_obj_new (char *decl, - sv_func_t **function_map, - int *function_output_map, - char *output_type_map); +int sv_obj_new (char *decl, + void (*function)(double *,double *), + char *input_map, + char *output_map); -sv_obj_t *sv_obj (char *name); +int sv_obj (char *name); int sv_obj_set_scale (sv_scale_t *scale); diff --git a/sushivision/tokens.c b/sushivision/tokens.c index 7c6940028..f7d0934c9 100644 --- a/sushivision/tokens.c +++ b/sushivision/tokens.c @@ -610,3 +610,25 @@ _sv_tokenlist *_sv_tokenize_namelist(char *in){ return ret; } +_sv_tokenlist *_sv_tokenize_noparamlist(char *in){ + if(!in)return NULL; + + char *l=strdup(in); + in=l; + + int i,n = splitcount(l,','); + _sv_tokenlist *ret = calloc(1,sizeof(*ret)); + + ret->n = n; + ret->list = calloc(n,sizeof(*ret->list)); + + for(i=0;ilist[i] = _sv_tokenize_name(l); + l=next; + } + free(in); + + return ret; +} + -- 2.11.4.GIT