/** * Object-to-Config function. * Creates a config-node (and subnodes) from a LedHardware model * @param c the current preferences context * @param n a freshly created prefs node that this function should fill with properties of obj * @param obj object of this class where preferences should be generated from * @result NFT_SUCCESS if everything went fine, NFT_FAILURE otherwise * @note you shouldn't call this function directly * It's used by nft_prefs_obj_to_node() etc. */ static NftResult _prefs_from_chain(NftPrefs * p, NftPrefsNode * n, void *obj, void *userptr) { if(!p || !n || !obj) NFT_LOG_NULL(NFT_FAILURE); /* chain to generate preferences from */ LedChain *c = obj; /* amount of LEDs in this chain - ledcount */ if(!nft_prefs_node_prop_int_set(n, LED_CHAIN_PROP_LEDCOUNT, led_chain_get_ledcount(c))) return NFT_FAILURE; /* pixel-format of this chain */ if(!nft_prefs_node_prop_string_set(n, LED_CHAIN_PROP_FORMAT, (char *) led_pixel_format_to_string (led_chain_get_format(c)))) return NFT_FAILURE; /* add all LEDs in this chain */ LedCount i; for(i = 0; i < led_chain_get_ledcount(c); i++) { /* generate prefs node from LED */ NftPrefsNode *node; if(! (node = led_prefs_led_to_node(p, led_chain_get_nth(c, i)))) return NFT_FAILURE; /* add node as child of this node */ if(!nft_prefs_node_add_child(n, node)) return NFT_FAILURE; } return NFT_SUCCESS; }
/** * send data in chain to hardware (only use this if hardware doesn't show data right after * data is received to avoid blanking. If the data is shown immediately, you have * to transmit it in _show() */ NftResult _send(void *privdata, LedChain * c, LedCount count, LedCount offset) { NFT_LOG(L_DEBUG, "Sending LDP8806 data"); struct priv *p = privdata; uint8_t *buf = led_chain_get_buffer(c); /* seek to offset */ int bytes_per_component = led_chain_get_buffer_size(c) / led_chain_get_ledcount(c); buf += offset * bytes_per_component; /* send buffer */ return spiTxData(p->fd, buf, bytes_per_component * count); }
/** build list of Leds */ static void _build( NiftyconfChain * c) { /* rebuild */ LedCount i; for(i = 0; i < led_chain_get_ledcount(chain_niftyled(c)); i++) { Led *led = led_chain_get_nth(chain_niftyled(c), i); GtkTreeIter iter; gtk_list_store_append(GTK_LIST_STORE(UI("liststore")), &iter); gtk_list_store_set(GTK_LIST_STORE(UI("liststore")), &iter, C_CHAIN_LED, i, C_CHAIN_ELEMENT, led_get_privdata(led), -1); led_set_highlighted(led_get_privdata(led), false); renderer_led_damage(led_get_privdata(led)); } gtk_widget_show(GTK_WIDGET(UI("treeview"))); }
/** * Config-to-Object function. * Creates a LedHardware model from a prefs node * @note you shouldn't call this function directly. * It's used by nft_prefs_obj_from_node() etc. */ static NftResult _prefs_to_hardware(LedPrefs * p, void **newObj, NftPrefsNode * n, void *userptr) { if(!p || !newObj || !n) NFT_LOG_NULL(NFT_FAILURE); /** initial result */ NftResult r = NFT_FAILURE; char *name = NULL; char *id = NULL; char *plugin_name = NULL; LedHardware *h = NULL; /* get hardware name */ if(! (name = nft_prefs_node_prop_string_get(n, LED_HARDWARE_PROP_NAME))) { NFT_LOG(L_ERROR, "\"hardware\" has no name"); goto _pth_end; } /* get plugin-name */ if(! (plugin_name = nft_prefs_node_prop_string_get(n, LED_HARDWARE_PROP_PLUGIN))) { NFT_LOG(L_ERROR, "\"hardware\" has no \"plugin\" type"); goto _pth_end; } /* get plugin-id */ if(!(id = nft_prefs_node_prop_string_get(n, LED_HARDWARE_PROP_ID))) { NFT_LOG(L_ERROR, "\"hardware\" has no \"id\" type"); goto _pth_end; } /* get stride */ LedCount stride; if(! (nft_prefs_node_prop_int_get (n, LED_HARDWARE_PROP_STRIDE, (int *) &stride))) { NFT_LOG(L_WARNING, "\"hardware\" has no \"stride\". Using 0 as default."); stride = 0; } /* create new hardware object */ if(!(h = led_hardware_new(name, plugin_name))) { NFT_LOG(L_ERROR, "Failed to initialize \"%s\" from \"%s\" plugin.", name, plugin_name); goto _pth_end; } /* set stride */ if(!(led_hardware_set_stride(h, stride))) { NFT_LOG(L_ERROR, "Failed to set stride (%d) of hardware \"%s\"", stride, name); goto _pth_end; } /* set id */ if(!(led_hardware_set_id(h, id))) { NFT_LOG(L_ERROR, "Failed to set ID \"%s\" of hardware \"%s\"", id, name); goto _pth_end; } /** @todo handle custom properties */ /* process child nodes */ LedPrefsNode *child; for(child = nft_prefs_node_get_first_child(n); child; child = nft_prefs_node_get_next(child)) { /* is child a tile node? */ if(led_prefs_is_tile_node(child)) { if(!led_hardware_append_tile (h, led_prefs_tile_from_node(p, child))) { NFT_LOG(L_ERROR, "Failed to add \"tile\" to \"%s\". Aborting.", name); goto _pth_end; } continue; } /* is child a chain node? */ else if(led_prefs_is_chain_node(child)) { LedChain *c; if(!(c = led_prefs_chain_from_node(p, child))) { NFT_LOG(L_ERROR, "Failed to create \"chain\" node of hardware %s", name); goto _pth_end; } if(!led_hardware_init (h, id, led_chain_get_ledcount(c), led_pixel_format_to_string(led_chain_get_format (c)))) { NFT_LOG(L_WARNING, "Failed to initialize hardware \"%s\"", name); } led_chain_destroy(c); } /* is child a plugin-property node? */ else if(strcmp (nft_prefs_node_get_name(child), LED_HARDWARE_PROPERTY_NAME) == 0) { char *name = NULL; char *type = NULL; char *value = NULL; /* get name of property */ if(! (name = nft_prefs_node_prop_string_get(child, LED_HARDWARE_PROPERTY_PROP_NAME))) { NFT_LOG(L_ERROR, "\"%s\" has no \"%s\" property", LED_HARDWARE_PROPERTY_NAME, LED_HARDWARE_PROPERTY_PROP_NAME); goto _pthp_end; } /* type of property */ if(! (type = nft_prefs_node_prop_string_get(child, LED_HARDWARE_PROPERTY_PROP_TYPE))) { NFT_LOG(L_ERROR, "\"%s\" has no \"%s\" property", LED_HARDWARE_PROPERTY_NAME, LED_HARDWARE_PROPERTY_PROP_TYPE); goto _pthp_end; } /* property value */ if(! (value = nft_prefs_node_prop_string_get(child, LED_HARDWARE_PROPERTY_PROP_VALUE))) { NFT_LOG(L_ERROR, "\"%s\" has no \"%s\" property", LED_HARDWARE_PROPERTY_NAME, LED_HARDWARE_PROPERTY_PROP_VALUE); goto _pthp_end; } /* decide about type */ switch (led_hardware_plugin_prop_type_from_string (type)) { /* int */ case LED_HW_CUSTOM_PROP_INT: { int integer; if(sscanf(value, "%32d", &integer) != 1) { NFT_LOG(L_ERROR, "Failed to parse integer from \"%s\" property (\"%s\")", LED_HARDWARE_PROPERTY_PROP_VALUE, value); goto _pthp_end; } if(!led_hardware_plugin_prop_set_int (h, name, integer)) { NFT_LOG(L_ERROR, "Failed to set \"%s\" = %d)", name, integer); goto _pthp_end; } break; } /* float */ case LED_HW_CUSTOM_PROP_FLOAT: { float f; if(sscanf(value, "%64f", &f) != 1) { NFT_LOG(L_ERROR, "Failed to parse float from \"%s\" property (\"%s\")", LED_HARDWARE_PROPERTY_PROP_VALUE, value); goto _pthp_end; } if(!led_hardware_plugin_prop_set_float (h, name, f)) { NFT_LOG(L_ERROR, "Failed to set \"%s\" = %f)", name, f); goto _pthp_end; } break; } /* string */ case LED_HW_CUSTOM_PROP_STRING: { if(!led_hardware_plugin_prop_set_string(h, name, value)) { NFT_LOG(L_ERROR, "Failed to set \"%s\" = \"%s\")", name, value); goto _pthp_end; } break; } /* huh? */ default: { NFT_LOG(L_ERROR, "Invalid plugin-property type: \"%s\"", type); break; } } _pthp_end: nft_prefs_free(name); nft_prefs_free(type); nft_prefs_free(value); continue; } else { NFT_LOG(L_WARNING, "Attempt to add \"%s\" node to hardware. Not allowed. (Ignoring node)", nft_prefs_node_get_name(child)); continue; } } /* everything pico bello */ r = NFT_SUCCESS; _pth_end: /* free strings */ nft_prefs_free(id); nft_prefs_free(plugin_name); nft_prefs_free(name); /* newly created hardware object */ *newObj = h; return r; }
/** renderer for chains */ static NftResult _render_chain( cairo_surface_t ** s, gpointer element) { if(!s || !*s || !element) NFT_LOG_NULL(NFT_FAILURE); /* get this chain */ NiftyconfChain *chain = (NiftyconfChain *) element; LedChain *c = chain_niftyled(chain); /* if dimensions changed, we need to allocate a new surface */ int width = (led_chain_get_max_x(c) + 1) * renderer_scale_factor(); int height = (led_chain_get_max_y(c) + 1) * renderer_scale_factor(); NiftyconfRenderer *r = chain_get_renderer(chain); if(!renderer_resize(r, width, height)) { g_error("Failed to resize renderer to %dx%d", width, height); return NFT_FAILURE; } /* create context for drawing */ cairo_t *cr = cairo_create(*s); /* disable antialiasing */ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); /* clear surface */ cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_rectangle(cr, 0, 0, (double) cairo_image_surface_get_width(*s), (double) cairo_image_surface_get_height(*s)); cairo_fill(cr); /* set line-width */ cairo_set_line_width(cr, 1); /* walk all LEDs */ LedCount i; for(i = 0; i < led_chain_get_ledcount(c); i++) { Led *l = led_chain_get_nth(c, i); NiftyconfLed *led = led_get_privdata(l); NiftyconfRenderer *lr = led_get_renderer(led); cairo_set_source_surface(cr, renderer_get_surface(lr), (double) led_get_x(l) * renderer_scale_factor(), (double) led_get_y(l) * renderer_scale_factor()); cairo_paint(cr); } cairo_destroy(cr); return NFT_SUCCESS; }
int main(int argc, char *argv[]) { nft_log_level_set(L_DEBUG); /* register new dummy hardware called "nlo01" */ LedHardware *h; if(!(h = led_hardware_new("nlo01", "dummy"))) { NFT_LOG(L_ERROR, "Hardware creation FAILED"); return -1; } /* initialize any hardware that can be found (id="*"), define 12 * connected LEDs (4 BGR pixels). Greyscale data should be provided in * unsigned 8-bit format */ if(!led_hardware_init(h, "*", 12, "BGR u8")) { NFT_LOG(L_ERROR, "failed to initialize hardware"); return -1; } /********************************************************************** * niftyled basically provides 2 ways to send data to LED hardware: * * 1. set "raw" greyscale value of a LED in a chain connected to a * correctly initialized LED hardware * * 1.1 use the API to set each greyscale value * * 1.2 directly write to the RAW buffer * * * 2. send a complete pixelframe and have niftyled translate that to * mapped LEDs connected to one or more LED hardware devices * according to the current setup configuration (where each LED * has been assigned a X/Y coordinate and a "Component" that refers * to a component of a pixel at this position in the pixelframe) */ /****** METHOD 1.1 *******/ /* get chain of this hardware */ LedChain *c = led_hardware_get_chain(h); /* set all LEDs to half brightness */ LedCount l; for(l = 0; l < led_chain_get_ledcount(c); l++) { led_chain_set_greyscale(c, l, 128); } /* send data to hardware */ led_hardware_send(h); /* show previously sent hardware (latch to LEDs) */ led_hardware_show(h); /****** METHOD 1.2 *******/ /* ...or access raw pixelbuffer */ uint8_t *pixels = led_chain_get_buffer(c); /* walk all pixels to turn on all LEDs */ int i; for(i = 0; i < 16; i++) pixels[i] = 0xff; /* send data to hardware */ led_hardware_send(h); /* show previously sent hardware (latch to LEDs) */ led_hardware_show(h); /****** METHOD 2 - s. ledcat sources *******/ /* deinitialize hardware */ led_hardware_deinit(h); return 0; }