Code Search for Developers
 
 
  

emview_source.c from EmStar at Krugle


Show emview_source.c syntax highlighted

/*
 *
 * Copyright (c) 2003 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "emview_i.h"
#include <math.h>

char emview_source_c_id[] = "$Id: emview_source.c,v 1.31 2006/05/30 20:10:52 nithya Exp $";

QUEUE_INST(emview_link_data, ptrs, links, link_data_t, link_source_t);
QUEUE_INST(emview_source_data, ptrs, values, source_data_t, simple_source_t);
QUEUE_INST(emview_source, ptrs, sources, source_t, emview_source_list_t);


/*
 *  creating a data source
 * 
 *  There are several different kinds of source that can be registered
 *   - simple sources (string and int)
 *   - link schemes (define arrows between nodes)
 *   - layout schemes (define node position on screen)
 *
 */

static
source_t *emview_source_create(const char *source_name, emview_source_type_t type, 
			       simple_source_attr_t *attr)
{
  source_t *src = NULL;
  simple_source_t *ss;
  link_source_t *ls;

  switch (type) {
  case EMVIEW_SOURCE_SIMPLE:
    ss = g_new0(simple_source_t, 1);
    ss->fast_data_lookup = g_hash_table_new(g_direct_hash, g_direct_equal);
    if (attr) {
      ss->attr = *attr;
      if (ss->attr.format_string) 
	ss->attr.format_string = strdup(ss->attr.format_string);
    }
    src = (source_t *)ss;
    break;

  case EMVIEW_SOURCE_LINK:
    ls = g_new0(link_source_t, 1);    
    src = (source_t *)ls;
    break;

  default:
    elog(LOG_CRIT, "source type not implemented yet");
    break;
  }

  if (src) {
    src->name = strdup(source_name);
    src->type = type;
  }

  return src;
}


/*
 *  source lookup
 */

source_t *emview_source_lookup_q(GQuark name)
{
  return (source_t *)g_hash_table_lookup(_core.source_list.fast_source_lookup, (void*)name);
}

source_t *emview_source_lookup(const char *name)
{
  GQuark q = g_quark_from_string(name);
  return emview_source_lookup_q(q);
}


/*
 *  simple_source data list primitives
 */

source_data_t *emview_source_data_create(simple_source_t *s, node_id_t id)
{
  source_data_t *d = g_new0(source_data_t, 1);

  /* initialize the data element */
  d->parent_source = (source_t*)s;
  d->id = id;
  d->not_present = 1;

  /* add it to the list */
  emview_source_data_push(s, d);
  g_hash_table_insert(s->fast_data_lookup, (void*)id, d);

  return d;
}


source_data_t *emview_source_data_lookup(simple_source_t *s, node_id_t id)
{
  source_data_t *d = (source_data_t *)g_hash_table_lookup(s->fast_data_lookup, (void*)id);
  if (d == NULL) 
    d = emview_source_data_create(s, id);
  return d;
}


int emview_source_get_int_data(char *source_name, node_id_t id, int *value)
{
  source_t *s = emview_source_lookup(source_name);
  if (s && s->type == EMVIEW_SOURCE_SIMPLE) {
    source_data_t *d = emview_source_data_lookup((simple_source_t *)s, id);
    if (d) {
      if (value)
	*value = d->int_value;
      return 0;
    }
  }
  return -1;
}

int emview_source_data_valid(source_data_t *data)
{
  return data && !data->not_present;
}

char *emview_source_data_string_value(source_data_t *data)
{
  return data->string_value;
}

emview_color_t emview_source_data_bg_color(source_data_t *data)
{
  return data->bg_color;
}

emview_color_t emview_source_data_fg_color(source_data_t *data)
{
  if (g_timer_isset(data->highlight_timeout))
    return EMVIEW_COLOR_RED;
  return data->fg_color;
}


/*
 *  source internal API: activates device dependencies
 */ 

void emview_source_activate_deps(source_t *src)
{
  GList *ptr;
  for (ptr=g_list_first(src->device_deps); ptr; 
       ptr=g_list_next(ptr)) {
    emview_device_activate((emview_device_t *)ptr->data);
  }
}


void emview_source_links_track_refs(link_source_t *ls)
{
  link_data_t *d;

  for (d=emview_link_data_top(ls); d; d=emview_link_data_next(d)) {
    emview_node_ref(d->src_node, d->src_component);
    emview_node_ref(d->dst_node, d->dst_component);
  }
}


void emview_draw_line_aux(GdkPixmap *fg_pixmap, GdkGC *gc,
			  int x1, int y1, int x2, int y2)
{
  if (((x1 < 0) && (x2 < 0)) ||
      ((y1 < 0) && (y2 < 0)) ||
      ((x1 > _core.gui.width) && (x2 > _core.gui.width)) ||      
      ((y1 > _core.gui.height) && (y2 > _core.gui.height)))
    return;
            
  gdk_draw_line(fg_pixmap, gc, x1, y1, x2, y2);
}


void emview_source_links_dump(buf_t *buf, link_source_t *ls)
{
  link_data_t *d;
  
  for (d=emview_link_data_top(ls); d; d=emview_link_data_next(d)) {
    bufprintf(buf, "Link from %d,%d to %d,%d, attr=%d",
	      d->src_node, d->src_component,
	      d->dst_node, d->dst_component,
	      d->attr.dir);
  }
}


void emview_source_links_draw(link_source_t *ls, node_t *n, emview_color_t default_color,
			      GQuark default_component, int annotations)
{
  link_data_t *d;
  static GdkGC *gc = NULL;

  if (gc == NULL) {
    gc = gdk_gc_new(_core.gui.window->window);
    gdk_gc_copy(gc, _core.gui.window->style->black_gc);
  }

  elog(LOG_DEBUG(10), "Drawing links for link source %s, node %d", 
       ls->super.name, n->id);

  for (d=emview_link_data_top(ls); d; d=emview_link_data_next(d)) {
    int sx, sy, dx, dy;
    int shift_x=0, shift_y=0;
    float t;
    int status1,status2;
    int active;

    /* skip links from other nodes */
    if (n->id != d->src_node)
      goto next;

    /* get endpoints */
    if ((status1 = emview_node_get_center
	 (d->src_node, (d->src_component ? d->src_component : default_component), &sx, &sy)) < 0) {
      elog(LOG_DEBUG(17), "Unable to get center of component");
      goto next;
    }

    if ((status2 = emview_node_get_center
	 (d->dst_node, (d->dst_component ? d->dst_component : default_component), &dx, &dy)) < 0) {
      elog(LOG_DEBUG(17), "Unable to get center of component");
      goto next;
    }

    /* a link is drawn active if both ends are active */
    active = status1 && status2;

    /*
     * compute line shift
     */

    t = atan2(-(dy-sy), (dx-sx));
    
    shift_x = LINK_OFFSET*cos(t + M_PI/2.0);
    shift_y = -LINK_OFFSET*sin(t + M_PI/2.0);

#if 0
    if ((d->src_node == 3) || (d->dst_node == 3)) 
      elog(LOG_INFO, "ep's %d,%d:%d,%d  %d,%d:%d,%d  angle=%f deg  %d %d", 
	   d->src_node, (d->src_component ? d->src_component : default_component), sx,sy,
	   d->dst_node, (d->dst_component ? d->dst_component : default_component), dx,dy,
	   r2d(t), shift_x, shift_y);
#endif

    switch (d->attr.dir) {
    case EMVIEW_LINKS_TO:
      sx -= shift_x;
      sy -= shift_y;
      dx -= shift_x;
      dy -= shift_y;
      break;

    case EMVIEW_LINKS_FROM:
      sx += shift_x;
      sy += shift_y;
      dx += shift_x;
      dy += shift_y;
      break;

    default:
      break;
    }

    if (annotations) {
      float frac=0.5;
      int ax,ay;

      /* skip if there's no annoation for this link */
      if (d->annotation == NULL)
	goto next;

      /* where does the annotation go? */
      switch (d->attr.dir) {
      case EMVIEW_LINKS_TO:
	frac += NOTE_FRAC; 
	break;

      case EMVIEW_LINKS_FROM:
	frac -= NOTE_FRAC; 
	break;

      default:
	break;
      }

      /* determine location */
      ax = sx+(dx-sx)*frac;
      ay = sy+(dy-sy)*frac;

      /* add it */
      emview_put_label(ax, ay, 0, 0, d->annotation,
		       EMVIEW_COLOR_WHITE, 
		       (d->attr.color == EMVIEW_COLOR_NONE) ? default_color : d->attr.color,
		       (d->attr.color == EMVIEW_COLOR_NONE) ? default_color : d->attr.color,
		       EMVIEW_CENTER, EMVIEW_CENTER, TEXT_NOTE_PAD,
		       0, 0, 0, !active);

      goto next;
    }

    /* draw the line */
    emview_set_fg_color(gc, (d->attr.color == EMVIEW_COLOR_NONE) ? default_color : d->attr.color,
			!active);    
    gdk_gc_set_line_attributes(gc, d->attr.weight ? d->attr.weight : 1,
			       d->attr.style, GDK_CAP_BUTT, GDK_JOIN_MITER);
    emview_draw_line_aux(_core.gui.fg_pixmap, gc, sx, sy, dx, dy);

    /* draw the arrow */
    if (d->attr.arrow && (d->attr.dir != EMVIEW_LINKS_BIDIR)) {
      float frac=0.5;
      int ax,ay,ax2,ay2;
      float t2=0;
      float t3=0;

      /* where does the arrow go? */
      switch (d->attr.dir) {
      case EMVIEW_LINKS_TO:
	frac += ARROW_FRAC; 
	t2 = t + ARROW_ANGLE;
	t3 = t - ARROW_ANGLE;
	break;

      case EMVIEW_LINKS_FROM:
	frac -= ARROW_FRAC; 
	t2 = t - (M_PI - ARROW_ANGLE);
	t3 = t + (M_PI - ARROW_ANGLE);
	break;

      default:
	break;
      }

      /* determine location */
      ax = sx+(dx-sx)*frac;
      ay = sy+(dy-sy)*frac;
      ax2 = ax+ARROW_LEN*cos(t2);
      ay2 = ay-ARROW_LEN*sin(t2);

      gdk_gc_set_line_attributes(gc, d->attr.weight ? d->attr.weight : 1,
				 GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
      emview_draw_line_aux(_core.gui.fg_pixmap, gc, ax, ay, ax2, ay2);

      ax2 = ax+ARROW_LEN*cos(t3);
      ay2 = ay-ARROW_LEN*sin(t3);

      emview_draw_line_aux(_core.gui.fg_pixmap, gc, ax, ay, ax2, ay2);
    }

  next:
    continue;
 
  }
}


/*
 *  source data update API
 */


source_data_t *emview_source_data_lookup_safe(char *source_name, node_id_t id)
{
  GQuark q = g_quark_from_string(source_name);
  return emview_source_data_lookup_safe_q(q, id);
}

source_data_t *emview_source_data_lookup_safe_q(GQuark source, node_id_t id)
{
  source_t *src = emview_source_lookup_q(source);
  source_data_t *d = NULL;
  
  if (src == NULL) {
    elog(LOG_WARNING, "Unknown source %s", g_quark_to_string(source));
    goto out;
  }

  switch (src->type) {
  case EMVIEW_SOURCE_LINK:
    /* ignore link sources.. */
    break;

  case EMVIEW_SOURCE_SIMPLE:
    /* lookup data for data sources */
    d = emview_source_data_lookup((simple_source_t *)src, id);
    break;
    
  default:
    elog(LOG_WARNING, "Unknown source type %d", src->type);
    break;
  }

 out:
  return d;
}


static
int emview_source_clear_data(void *data, int interval, g_event_t *event)
{
  source_data_t *d = (source_data_t *)data;
  d->not_present = 1;
  return TIMER_DONE;
}


/* updates a simple source with a string value */
int emview_update_source(char *source_name, node_id_t id, char *value)
{
  return emview_update_source_q(g_quark_from_string(source_name), id, value);
}

int emview_update_source_q(GQuark source_name, node_id_t id, char *value)
{
  source_data_t *d = emview_source_data_lookup_safe_q(source_name, id);

  /* heard from this node */
  emview_node_heard(id, 0);

  if (d) {
    simple_source_t *s = (simple_source_t *)d->parent_source;

    /* set timer if requested and value changed */
    if (s->attr.note_change_timeout &&
	(d->string_value && strcmp(d->string_value,value))) {
      g_event_destroy(d->highlight_timeout);
      g_timer_add(s->attr.note_change_timeout * 1000,
		  NULL, NULL, NULL, &(d->highlight_timeout));
    }
    
    /* if data value is to time out, set the timer */
    if (s->attr.data_timeout) {
      g_event_destroy(d->data_value_timeout);
      g_timer_add(s->attr.data_timeout * 1000,
		  emview_source_clear_data, d, NULL, 
		  &(d->data_value_timeout));      
    }
    
    /* replace string value */
    if (d->string_value) free(d->string_value);
    d->string_value = strdup(value);

    /* try to convert to int */
    d->int_value = atoi(value);

    /* value present */
    d->not_present = 0;

    /* init colors */
    d->bg_color = EMVIEW_COLOR_WHITE;
    d->fg_color = EMVIEW_COLOR_BLACK;

    return 0;
  }
  else return -1;
}


/* updates a simple source with an int value */
/* $$$$ more cut and paste nonsense here */
int emview_update_source_int(char *source_name, node_id_t id, int value)
{
  return emview_update_source_int_q(g_quark_from_string(source_name), id, value);
}

int emview_update_source_int_q(GQuark source_name, node_id_t id, int value)
{
  source_data_t *d = emview_source_data_lookup_safe_q(source_name, id);

  /* heard from this node */
  emview_node_heard(id, 0);

  if (d) {
    char str[256];
    simple_source_t *s = (simple_source_t *)d->parent_source;

    /* set timer if requested and value changed */
    if ((d->int_value != value) &&
	s->attr.note_change_timeout) {
      g_event_destroy(d->highlight_timeout);
      g_timer_add(s->attr.note_change_timeout * 1000,
		  NULL, NULL, NULL, &(d->highlight_timeout));
    }

    /* if data value is to time out, set the timer */
    if (s->attr.data_timeout) {
      g_event_destroy(d->data_value_timeout);
      g_timer_add(s->attr.data_timeout * 1000,
		  emview_source_clear_data, d, NULL, 
		  &(d->data_value_timeout));      
    }
    
    /* set new int value */
    d->int_value = value;

    /* clear previous string */
    if (d->string_value) free(d->string_value);
    d->string_value = NULL;

    /* convert to string */
    sprintf(str, (s->attr.format_string ? s->attr.format_string : "%d"), value);
    d->string_value = strdup(str);

    /* set present bit */
    d->not_present = 0;

    /* init colors */
    d->bg_color = EMVIEW_COLOR_WHITE;
    d->fg_color = EMVIEW_COLOR_BLACK;

    return 0;
  }
  else return -1;
}


/* 
 * link scheme control methods 
 */

static
void emview_link_data_destroy(link_data_t *ld)
{
  if (ld->annotation)
    free(ld->annotation);
  free(ld);
}

int emview_clear_links_q(GQuark source)
{
  source_t *src = emview_source_lookup_q(source);
  link_source_t *ls = (link_source_t *)src;
  link_data_t *ld;
  
  if (src->type != EMVIEW_SOURCE_LINK) {
    elog(LOG_WARNING, "Clear links called on non LINK source");
    return -1;
  }

  while ((ld = emview_link_data_pop(ls))) {
    emview_link_data_destroy(ld);
  }

  return 0;
}


/* clear links 'from' node_id, 'to' node_id, or either way */ 
int emview_clear_links_to_node_q(GQuark source, node_id_t node_id, GQuark component,
				 emview_link_dir_t from)
{
  source_t *src = emview_source_lookup_q(source);
  link_source_t *ls = (link_source_t *)src;
  link_data_t *ld;
  link_data_t *tmp;
  int count=0;

  if (src == NULL) {
    elog(LOG_WARNING, "Source %s not found!", g_quark_to_string(source));
    return -1;
  }

  if (src->type != EMVIEW_SOURCE_LINK) {
    elog(LOG_WARNING, "Clear links to node called on non LINK source");
    return -1;
  }
  
  for (ld = emview_link_data_top(ls); ld; ld = tmp) {
    tmp = emview_link_data_next(ld);

    switch (from) {
    case EMVIEW_LINKS_FROM:
      if (((ld->src_node == node_id) && 
	   (!component || (ld->src_component == component)) &&
	   (ld->attr.dir != EMVIEW_LINKS_TO)) ||
	  ((ld->dst_node == node_id) && 
	   (!component || (ld->dst_component == component)) &&
	   (ld->attr.dir != EMVIEW_LINKS_FROM)))
	goto clear;
      break;

    case EMVIEW_LINKS_TO:
      if (((ld->src_node == node_id) && 
	   (!component || (ld->src_component == component)) &&
	   (ld->attr.dir != EMVIEW_LINKS_FROM)) ||
	  ((ld->dst_node == node_id) && 
	   (!component || (ld->dst_component == component)) &&
	   (ld->attr.dir != EMVIEW_LINKS_TO)))
	goto clear;
      break;

    default:
      if (((ld->src_node == node_id) &&
	   (!component || (ld->src_component == component))) ||
	  ((ld->dst_node == node_id) &&
	   (!component || (ld->dst_component == component))))
	goto clear;
      break;
    }

    continue;

  clear:
    count++;
    emview_link_data_remove(ls, ld);
    emview_link_data_destroy(ld);
  }

  elog(LOG_DEBUG(5), "Cleared %d links", count);
  return count;  
}



/* clear all links that have a matching private_data attribute.
 * (i.e. the attribute passed to this function matches the data
 * associated with the link when it was created) */
int emview_clear_links_with_data_q(GQuark source, void *private_data)
{
  source_t *src = emview_source_lookup_q(source);
  link_source_t *ls = (link_source_t *)src;
  link_data_t *ld;
  link_data_t *tmp;
  int count=0;

  if (src->type != EMVIEW_SOURCE_LINK) {
    elog(LOG_WARNING, "Clear links to node called on non LINK source");
    return -1;
  }
  
  for (ld = emview_link_data_top(ls); ld; ld = tmp) {
    tmp = emview_link_data_next(ld);

    if (ld->attr.private_data != private_data)
      continue;

    count++;
    emview_link_data_remove(ls, ld);
    emview_link_data_destroy(ld);
  }

  elog(LOG_DEBUG(5), "Cleared %d links", count);
  return count;  
}


/* note: does not remove or replace existing links, just inserts a new one */
int emview_update_link_q(GQuark link_source,
			 node_id_t src, GQuark src_comp, 
			 node_id_t dst, GQuark dst_comp, 
			 char *note, link_attr_t *attr)
{
  link_attr_t defaults = {
    weight: 1,
    style: GDK_LINE_SOLID,
    dir: EMVIEW_LINKS_FROM
  };

  source_t *l_src = emview_source_lookup_q(link_source);
  link_source_t *ls = (link_source_t *)l_src;
  link_data_t *ld;

  if (l_src->type != EMVIEW_SOURCE_LINK) {
    elog(LOG_WARNING, "Update link called on non LINK source");
    return -1;
  }

  ld = g_new0(link_data_t, 1);

  /* heard from this node */
  emview_node_heard(src, 0);
  emview_node_heard(dst, 0);

  if (note)
    ld->annotation = strdup(note);

  if (attr)
    ld->attr = *attr;
  else
    ld->attr = defaults;

  ld->src_node = src;
  ld->src_component = src_comp;

  ld->dst_node = dst;
  ld->dst_component = dst_comp;
  
  emview_link_data_push(ls, ld);

  return 0;
}


/*
 *  source registration API 
 */


void emview_register_source_q(emview_device_t *dev_dep, GQuark q,
			      simple_source_attr_t *attr)
{
  emview_register_source(dev_dep, g_quark_to_string(q), attr); 
}

void emview_register_source(emview_device_t *dev_dep, const char *source_name, 
			    simple_source_attr_t *attr)
{
  source_t *src;

  /* get quark */
  GQuark q = g_quark_from_string(source_name);

  /* lookup source and emit error if duplicate */
  if (emview_source_lookup(source_name)) {
    elog(LOG_CRIT, "Attempt to register duplicate source %s", source_name);
    return;
  }

  /* create a new source of this type */ 
  src = emview_source_create(source_name, EMVIEW_SOURCE_SIMPLE, attr);
  
  /* add to the core */
  emview_source_push(&(_core.source_list), src);
  g_hash_table_insert(_core.source_list.fast_source_lookup, (void*)q, src);

  /* add this device dep */
  if (dev_dep)
    emview_source_add_dep(source_name, dev_dep);
}


/* $$$ let's get rid of this cut and paste someday!!! */
void emview_register_link_source(emview_device_t *dev_dep, const char *source_name)
{
  source_t *src;

  /* get quark */
  GQuark q = g_quark_from_string(source_name);

  /* lookup source and emit error if duplicate */
  if (emview_source_lookup(source_name)) {
    elog(LOG_CRIT, "Attempt to register duplicate source %s", source_name);
    kill(getpid(), SIGSEGV);
    exit(1);
  }

  /* create a new source of this type */ 
  src = emview_source_create(source_name, EMVIEW_SOURCE_LINK, NULL);
  
  /* add to the core */
  emview_source_push(&(_core.source_list), src);
  g_hash_table_insert(_core.source_list.fast_source_lookup, (void*)q, src);

  /* add this device dep */
  if (dev_dep)
    emview_source_add_dep(source_name, dev_dep);
}


/* adds additional device dependencies to a given component */
void emview_source_add_dep(const char *name, emview_device_t *dev_dep)
{
  source_t *src = emview_source_lookup(name);
  if (src) 
    src->device_deps = g_list_prepend(src->device_deps, dev_dep);
}


/* adds a source dependency to this source */
void emview_source_add_source_dep(const char *depender, const char *dependee, 
				  void *update_cb_func, void *data)
{
  source_t *dst = emview_source_lookup(depender);
  source_t *src = emview_source_lookup(dependee);
  GList *ptr;
  
  /* $$$ this is a temporary solution.. !!! */
  /* copy the device deps from src to dst */
  ptr = g_list_concat(dst->device_deps, g_list_copy(src->device_deps));

  /* $$$ future: keep track of source deps and implement cb functions */  
}


/* returns the type of source this is (link scheme, source, etc.) */
emview_source_type_t emview_source_get_type(char *name)
{
  source_t *src = emview_source_lookup(name);
  if (src) 
    return src->type;  
  return -1;
}


/* reset all data sources for this node */
void emview_source_reset_node(node_id_t id)
{
  source_t *src;
  source_data_t *d;
  
#ifdef CLEAR_REFS_ON_RESET
  node_t *n;
  /* clear referenced bits */
  n = emview_node_lookup_nocreate(id);
  if (n) emview_node_clear_refs(n);
#endif
  
  for (src = emview_source_top(&(_core.source_list)); src;
       src = emview_source_next(src)) {

    switch (src->type) {
    case EMVIEW_SOURCE_SIMPLE:
      d = emview_source_data_lookup((simple_source_t *)src, id);
      d->not_present = 1;
      break;

    case EMVIEW_SOURCE_LINK:
      emview_clear_links_to_node_q(g_quark_from_string(src->name), id, 0, EMVIEW_LINKS_FROM);
      break;

    default:
      elog(LOG_WARNING, "source type %d not implemented", src->type);
    }    
  }
}


/*
 *  colormaps
 */

emview_color_t emview_assign_color(char *source_name, int value)
{
  source_t *src;
  int i,j,min_i=-1,min_count=-1;
  
  if (value == 0) return 0;
  src = emview_source_lookup(source_name);

  for (i=0; i<EMVIEW_MAX_COLORS-2; i++) 
    for (j=0; j<EMVIEW_MAX_OVERLOAD; j++) {
      if (src->colormap[i][j] == 0) {
	if (min_count < 0 || j < min_count) {
	  min_i = i;
	  min_count = j;
	}
	break;
      }
      if (src->colormap[i][j] == value)
	return i+1;
    }

  if (min_i < 0)
    return 0;
  src->colormap[min_i][min_count] = value;
  return min_i+1;
}


emview_color_t emview_query_color(char *source_name, int value)
{
  source_t *src;
  int i,j;
  
  if (value == 0) return 0;
  src = emview_source_lookup(source_name);

  for (i=0; i<EMVIEW_MAX_COLORS-2; i++) 
    for (j=0; j<EMVIEW_MAX_OVERLOAD; j++) {
      if (src->colormap[i][j] == 0) 
	return 0;
      if (src->colormap[i][j] == value)
	return i+1;
    }

  return 0;
}


/*
 *  menus
 */

static int b0rken_gtk = 0;

static
void emview_layout_set_check(link_source_t *ls)
{
  if (ls->menu) {
    b0rken_gtk = 1;
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ls->menu), (ls == _core.gui.layout_link_source));
    b0rken_gtk = 0;
  }
}

static
int emview_layout_config(void *data)
{
  source_t *src;
  link_source_t *ls = (link_source_t*)data;

  if (b0rken_gtk) return TRUE;

  /* set the layout link source */
  _core.gui.layout_link_source = ls;

  /* set grid bit if this is reported */
  _core.gui.do_grid = (ls == _core.source_list.reported);

  emview_layout_set_check(_core.source_list.grid);
  emview_layout_set_check(_core.source_list.reported);
  
  for (src = emview_source_top(&(_core.source_list)); src;
       src = emview_source_next(src))
    if (src->type == EMVIEW_SOURCE_LINK) 
      emview_layout_set_check((link_source_t *)src);

  /* repos now */
  emview_repos_nodes();
  
  return TRUE;
}


void emview_build_layout_menu()
{ 
  /* layouts menu */
  GtkWidget *menu = emview_toplevel_menu("Layout", NULL);

  _core.source_list.grid =
    (link_source_t *)emview_source_create(EMVIEW_LAYOUT_GRID, EMVIEW_SOURCE_LINK, NULL);
  _core.source_list.grid->menu = 
    emview_menu_item(menu, gtk_check_menu_item_new_with_label(EMVIEW_LAYOUT_GRID),
		     emview_layout_config, _core.source_list.grid);

  _core.source_list.reported =
    (link_source_t *)emview_source_create(EMVIEW_LAYOUT_REPORTED, EMVIEW_SOURCE_LINK, NULL);
  _core.source_list.reported->menu =
    emview_menu_item(menu, gtk_check_menu_item_new_with_label(EMVIEW_LAYOUT_REPORTED),
		     emview_layout_config, _core.source_list.reported);

#if 0
  {   /* error in this code.. do later $$$$ */
    source_t *src;
    link_source_t *ls; 
    GtkWidget *submenu;
    
    submenu = emview_sub_menu(menu, "Logical/Graph");
    
    for (src = emview_source_top(&(_core.source_list)); src;
	 src = emview_source_next(src))
      if (src->type == EMVIEW_SOURCE_LINK) {
	ls = (link_source_t *)src;
	ls->menu = 
	  emview_menu_item(submenu, gtk_check_menu_item_new_with_label(src->name),
			   emview_layout_config, ls);
      }
  }
#endif

  _core.source_list.hide_inactive = 0;
  _core.source_list.reported->menu =
    emview_check_menu_item(menu, "Hide Inactive Nodes",
			   &(_core.source_list.hide_inactive));

  /* default to grid */
  _core.gui.layout_link_source = _core.source_list.grid;
  emview_layout_set_check(_core.source_list.grid);
}


/*
 *  status report
 */ 

static
int emview_sources_status_printable(status_context_t *info, buf_t *buf)
{
  source_t *src;

  bufprintf(buf, "Sources:\n");
  for (src = emview_source_top(&(_core.source_list)); src;
       src = emview_source_next(src)) {
    //simple_source_t *simple = (simple_source_t *)src;
    //link_source_t *link = (link_source_t *)src;
    GList *ptr;

    bufprintf(buf, "  Source '%s', type %d\n    Deps: ", src->name, src->type);
    
    for (ptr=g_list_first(src->device_deps); ptr; 
	 ptr=g_list_next(ptr)) {
      emview_device_t *dev = (emview_device_t *)(ptr->data);
      bufprintf(buf, "%s[%d], ", dev->opts.name, dev->data_id);
    }
    bufprintf(buf, "\n");

    switch (src->type) {
    case EMVIEW_SOURCE_SIMPLE:      
      break;

    case EMVIEW_SOURCE_LINK:
      break;

    default:
      elog(LOG_WARNING, "source type %d not implemented", src->type);
    }    
  }
  
  return STATUS_MSG_COMPLETE;
}


void emview_print_source_data(char *field, source_data_t *d, buf_t *buf)
{
  bufprintf(buf, "      %s: ", field);
  if (d == NULL) bufprintf(buf, "Empty\n");
  else if (d->parent_source) bufprintf(buf, "%s\n", d->parent_source->name);
  else bufprintf(buf, "***non-empty, invalid parent!!!\n");
}


void emview_sources_init()
{
  _core.source_list.fast_source_lookup = g_hash_table_new(g_direct_hash, g_direct_equal); 

  /* configure (optional) status device */
  {
    status_dev_opts_t opts = {
      device: {
	devname: "/dev/emview/sources"
      },
      printable: emview_sources_status_printable
    };  
    g_status_dev(&opts, &(_core.source_list.stat));
  }
}






See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  emview_analysis.c
  emview_analysis.h
  emview_box_component.c
  emview_component.c
  emview_component.h
  emview_config.c
  emview_config.h
  emview_device.c
  emview_device.h
  emview_gui.c
  emview_gui.h
  emview_gui_menu.c
  emview_i.h
  emview_main.c
  emview_node.c
  emview_node.h
  emview_node_component.c
  emview_slots.c
  emview_source.c
  emview_source.h