diff --git a/Makefile b/Makefile index 7535ab0..7e8251c 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,13 @@ +LUA_CFLAGS=$(shell pkg-config --cflags lua) +LUA_LIBS=$(shell pkg-config --libs lua) + CC=gcc -CFLAGS+=-O3 -Wall -march=native -pedantic -std=c99 -D_POSIX_C_SOURCE=20120607L -D_XOPEN_SOURCE -LIBS=-lm -lpthread -lrt +CFLAGS+=-O2 -Wall -march=native -pedantic -std=c99 -D_POSIX_C_SOURCE=20120607L -D_XOPEN_SOURCE $(LUA_CFLAGS) +LIBS=-lm -lpthread -lrt $(LUA_LIBS) TARGET=musiclight2 -SOURCE=main.c fft.c utils.c ws2801.c -DEPS=config.h fft.h utils.h ws2801.h +SOURCE=main.c fft.c utils.c ws2801.c lua_utils.c lua_wrappers.c +DEPS=config.h fft.h utils.h ws2801.h lua_utils.h lua_wrappers.h OBJ=$(patsubst %.c, %.o, $(SOURCE)) diff --git a/config.h b/config.h index 4d2103b..3de59bf 100644 --- a/config.h +++ b/config.h @@ -30,9 +30,6 @@ // update rate for the led strip (in seconds) #define LED_INTERVAL 0.03 -// number of modules in LED strip -#define NUM_MODULES 20 - // frequency ranges for the base colors #define RED_MIN_FREQ 0 #define RED_MAX_FREQ 400 @@ -43,10 +40,6 @@ #define COLOR_MAX_REDUCTION_FACTOR 0.9998 -#define CENTER_MODULE 10 - -#define GAMMA 2.0 - // sample data types typedef int16_t sample; typedef int64_t sample_sum; diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..bb223d5 --- /dev/null +++ b/config.lua @@ -0,0 +1,7 @@ +WS2801_HOST = "192.168.23.222" +WS2801_PORT = 2703 + +NUM_MODULES = 20 +CENTER_MODULE = 10 + +GAMMA = 2.0 diff --git a/lua_utils.c b/lua_utils.c new file mode 100644 index 0000000..b715a8c --- /dev/null +++ b/lua_utils.c @@ -0,0 +1,73 @@ +/* + * vim: sw=2 ts=2 expandtab + * + * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"): + * wrote this file. As long as you retain this notice you can + * do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb + */ + +#include +#include +#include + +#include "lua_utils.h" + +void lua_showerror(lua_State *L, const char *msg) { + fprintf(stderr, "\nLUA ERROR:\n %s: %s\n\n", + msg, lua_tostring(L, -1)); +} + +void lua_pushdoublearray(lua_State *L, double *numbers, size_t len) { + size_t i; + + // create an empty table + lua_createtable(L, len, 0); + + for(i = 0; i < len; i++) { + // push key and value + lua_pushnumber(L, i+1); // lua arrays count from 1 + lua_pushnumber(L, numbers[i]); + + // store the values in the table + lua_settable(L, -3); + } +} + +void lua_pushsamplearray(lua_State *L, sample *numbers, size_t len) { + size_t i; + + // create an empty table + lua_createtable(L, len, 0); + + for(i = 0; i < len; i++) { + // push key and value + lua_pushnumber(L, i+1); // lua arrays count from 1 + lua_pushnumber(L, numbers[i]); + + // store the values in the table + lua_settable(L, -3); + } +} + +void lua_readdoublearray(lua_State *L, double *numbers, size_t len) { + size_t k; + double v; + + // go to the top of the stack + lua_pushnil(L); + + while(lua_next(L, -2)) { + v = lua_tonumber(L, -1); + lua_pop(L, 1); + k = lua_tointeger(L, -1); + + if(k > len || k < 1) { + fprintf(stderr, "Warning: Lua index (%u) is out of C array range (%u)!\n", k, len); + } else { + numbers[k-1] = v; + } + } + + lua_pop(L, 1); +} diff --git a/lua_utils.h b/lua_utils.h new file mode 100644 index 0000000..ce60603 --- /dev/null +++ b/lua_utils.h @@ -0,0 +1,20 @@ +/* + * vim: sw=2 ts=2 expandtab + * + * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"): + * wrote this file. As long as you retain this notice you can + * do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb + */ + +#ifndef LUA_UTILS_H +#define LUA_UTILS_H + +#include "config.h" + +void lua_showerror(lua_State *L, const char *msg); +void lua_pushdoublearray(lua_State *L, double *numbers, size_t len); +void lua_pushsamplearray(lua_State *L, sample *numbers, size_t len); +void lua_readdoublearray(lua_State *L, double *numbers, size_t len); + +#endif // LUA_UTILS_H diff --git a/lua_wrappers.c b/lua_wrappers.c new file mode 100644 index 0000000..d366e64 --- /dev/null +++ b/lua_wrappers.c @@ -0,0 +1,73 @@ +/* + * vim: sw=2 ts=2 expandtab + * + * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"): + * wrote this file. As long as you retain this notice you can + * do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb + */ + +#include + +#include +#include +#include + +#include "fft.h" + +#include "config.h" + +#include "lua_utils.h" +#include "lua_wrappers.h" + +extern sem_t fftSemaphore; +extern double fft[BLOCK_LEN]; +extern sample signal[BLOCK_LEN]; +extern double rms; + +static int l_get_energy_in_band(lua_State *L) { + int lowerFreq, higherFreq; + + luaL_checktype(L, 1, LUA_TNUMBER); + lowerFreq = lua_tointeger(L, 1); + + luaL_checktype(L, 2, LUA_TNUMBER); + higherFreq = lua_tointeger(L, 2); + + sem_wait(&fftSemaphore); + lua_pushnumber(L, get_energy_in_band(fft, lowerFreq, higherFreq)); + sem_post(&fftSemaphore); + + return 1; // number of arguments +} + +static int l_get_fft(lua_State *L) { + sem_wait(&fftSemaphore); + lua_pushdoublearray(L, fft, BLOCK_LEN); + sem_post(&fftSemaphore); + + return 1; // number of return values +} + +static int l_get_signal(lua_State *L) { + sem_wait(&fftSemaphore); + lua_pushsamplearray(L, signal, BLOCK_LEN); + sem_post(&fftSemaphore); + + return 1; // number of return values +} + +static int l_get_rms(lua_State *L) { + sem_wait(&fftSemaphore); + lua_pushnumber(L, rms); + sem_post(&fftSemaphore); + + return 1; // number of return values +} + +void lua_register_funcs(lua_State *L) { + lua_register(L, "get_energy_in_band", l_get_energy_in_band); + lua_register(L, "get_fft", l_get_fft); + lua_register(L, "get_signal", l_get_signal); + lua_register(L, "get_rms", l_get_rms); +} diff --git a/lua_wrappers.h b/lua_wrappers.h new file mode 100644 index 0000000..28da0eb --- /dev/null +++ b/lua_wrappers.h @@ -0,0 +1,21 @@ +/* + * vim: sw=2 ts=2 expandtab + * + * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"): + * wrote this file. As long as you retain this notice you can + * do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb + */ + +#ifndef LUA_WRAPPERS_H +#define LUA_WRAPPERS_H + +void lua_register_funcs(lua_State *L); + +/* +static int l_get_energy_in_band(lua_State *L); +static int l_get_fft(lua_State *L); +static int l_get_signal(lua_State *L); +*/ + +#endif // LUA_WRAPPERS_H diff --git a/main.c b/main.c index e0e2c44..5166168 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,14 @@ #include #include #include +#include + +#include +#include +#include + +#include "lua_utils.h" +#include "lua_wrappers.h" #include "fft.h" #include "utils.h" @@ -27,12 +35,9 @@ // Number of new samples put into the buffer each frame #define READ_SAMPLES (BLOCK_LEN / BUFFER_PARTS) -#define COLORBUF_SIZE (2*(NUM_MODULES+1)) -#define CENTER_POS (2*CENTER_MODULE) - double fft[BLOCK_LEN]; +sample signal[BLOCK_LEN]; double rms; -double redEnergy, greenEnergy, blueEnergy; double lastUpdateTime = 0; sem_t fftSemaphore; @@ -72,7 +77,7 @@ void* fft_thread(void *param) { tmpRMS = 0; for(i = 0; i < BLOCK_LEN; i++) { - tmpRMS += block[i]*block[i]; + tmpRMS += buffer[i]*buffer[i]; } tmpRMS = sqrt(tmpRMS/BLOCK_LEN); @@ -80,10 +85,8 @@ void* fft_thread(void *param) { sem_wait(&fftSemaphore); memcpy(fft, tmpFFT, sizeof(fft)); + memcpy(signal, buffer, sizeof(signal)); rms = tmpRMS; - redEnergy = get_energy_in_band(fft, RED_MIN_FREQ, RED_MAX_FREQ); - greenEnergy = get_energy_in_band(fft, GREEN_MIN_FREQ, GREEN_MAX_FREQ); - blueEnergy = get_energy_in_band(fft, BLUE_MIN_FREQ, BLUE_MAX_FREQ); curTime = get_hires_time(); lastUpdateTime = curTime; @@ -113,64 +116,97 @@ void* fft_thread(void *param) { return NULL; } -double gamma_correct(double d) { - return pow(d, GAMMA); -} - -void text_bar(double fill) { - int fillCnt = 10 * fill; - int i; - - for(i = 0; i < fillCnt; i++) { - printf("|"); - } - - for(; i < 10; i++) { - printf("-"); - } -} - -double weighted_avg(uint8_t colorBuf[COLORBUF_SIZE][3], int channel, int centerPos) { - return 0.20 * colorBuf[centerPos - 1][channel] + - 0.60 * colorBuf[centerPos][channel] + - 0.20 * colorBuf[centerPos + 1][channel]; -} - -void show_status(double curRed, double maxRed, double curGreen, double maxGreen, double curBlue, double maxBlue) { - printf("\r"); - - printf("[\033[31m"); - text_bar(curRed / maxRed); - printf("\033[0m] "); - printf("\033[1;31m%7.2e\033[0m ", maxRed / (RED_MAX_FREQ - RED_MIN_FREQ)); - - printf("[\033[32m"); - text_bar(curGreen / maxGreen); - printf("\033[0m] "); - printf("\033[1;32m%7.2e\033[0m ", maxGreen / (GREEN_MAX_FREQ - GREEN_MIN_FREQ)); - - printf("[\033[34m"); - text_bar(curBlue / maxBlue); - printf("\033[0m] "); - printf("\033[1;34m%7.2e\033[0m ", maxBlue / (BLUE_MAX_FREQ - BLUE_MIN_FREQ)); - - fflush(stdout); +double gamma_correct(double d, double gamma) { + return pow(d, gamma); } int main(int argc, char **argv) { double nextFrame = get_hires_time() + LED_INTERVAL; - int i, j; + int i; pthread_t fftThread; int active = 1; - uint8_t colorBuf[COLORBUF_SIZE][3]; + double *red; + double *green; + double *blue; - double curRedEnergy, curGreenEnergy, curBlueEnergy; - double maxRedEnergy = 1, maxGreenEnergy = 1, maxBlueEnergy = 1; + int useFading, fadeStep; - memset(colorBuf, 0, sizeof(colorBuf)); + if(argc < 2) { + fprintf(stderr, "LUA script file must be given as command line argument!\n"); + return 1; + } + + // initialize lua + lua_State *L = lua_open(); + + // load the lua libraries + luaL_openlibs(L); + + // register local functions + lua_register_funcs(L); + + // load the configuration from "config.lua" + if(luaL_dofile(L, "config.lua")) { + lua_showerror(L, "luaL_dofile(config.lua) failed."); + return 1; + } + + lua_getglobal(L, "WS2801_HOST"); + if(!lua_isstring(L, -1)) return 2; + const char *host = lua_tostring(L, -1); + + lua_getglobal(L, "WS2801_PORT"); + if(!lua_isnumber(L, -1)) return 2; + unsigned short port = lua_tointeger(L, -1); + + lua_getglobal(L, "GAMMA"); + if(!lua_isnumber(L, -1)) return 2; + double gamma = lua_tonumber(L, -1); + + lua_getglobal(L, "NUM_MODULES"); + if(!lua_isnumber(L, -1)) return 2; + int num_modules = lua_tointeger(L, -1); + + lua_getglobal(L, "CENTER_MODULE"); + if(!lua_isnumber(L, -1)) return 2; + int center_module = lua_tointeger(L, -1); + + // allocate arrays + red = malloc(num_modules * sizeof(double)); + green = malloc(num_modules * sizeof(double)); + blue = malloc(num_modules * sizeof(double)); + + // load and initialize the script + if(luaL_loadfile(L, argv[1])) { + lua_showerror(L, "luaL_loadfile(cmdline_argument) failed."); + } + + // priming call: read the lua file to make functions known + if(lua_pcall(L, 0, 0, 0)) { + lua_showerror(L, "lua_pcall failed."); + } + + // call the init function + lua_getglobal(L, "init"); + lua_pushnumber(L, num_modules); + lua_pushnumber(L, center_module); + if(lua_pcall(L, 2, 1, 0)) { + lua_showerror(L, "lua_pcall(init) failed."); + } + + fadeStep = lua_tointeger(L, -1); + useFading = fadeStep > 0; + if(useFading) { + ws2801_set_fadestep(fadeStep); + printf("Fading enabled with fadestep %i.\n", fadeStep); + } + + // initialize the WS2801 library + printf("Connecting to %s:%i\n", host, port); + ws2801_init(host, port); // create semaphores sem_init(&fftSemaphore, 0, 1); @@ -178,68 +214,41 @@ int main(int argc, char **argv) { // run the fft thread pthread_create(&fftThread, NULL, fft_thread, NULL); - ws2801_init(HOST, PORT); - while(running) { - for(i = COLORBUF_SIZE-1; i >= 0; i--) { - int pos = CENTER_POS + i; - if(pos < COLORBUF_SIZE-1) { - for(j = 0; j < 3; j++) { - colorBuf[pos][j] = colorBuf[pos - 1][j]; - } - } - - pos = CENTER_POS - i; - if(pos >= 0) { - for(j = 0; j < 3; j++) { - colorBuf[pos][j] = colorBuf[pos + 1][j]; - } - } - } - if(active) { - sem_wait(&fftSemaphore); - curRedEnergy = redEnergy; - curGreenEnergy = greenEnergy; - curBlueEnergy = blueEnergy; - sem_post(&fftSemaphore); - - maxRedEnergy *= COLOR_MAX_REDUCTION_FACTOR; - if(curRedEnergy > maxRedEnergy) { - maxRedEnergy = curRedEnergy; + // call the periodic() function from LUA + lua_getglobal(L, "periodic"); + if(lua_pcall(L, 0, 3, 0)) { // no arguments, 3 return values + lua_showerror(L, "lua_pcall(periodic) failed."); } - maxGreenEnergy *= COLOR_MAX_REDUCTION_FACTOR; - if(curGreenEnergy > maxGreenEnergy) { - maxGreenEnergy = curGreenEnergy; + // read the return values (reverse order, as lua uses a stack) + lua_readdoublearray(L, blue, num_modules); + lua_readdoublearray(L, green, num_modules); + lua_readdoublearray(L, red, num_modules); + + if(useFading) { + for(i = 0; i < num_modules; i++) { + ws2801_fade_color(i, + 255 * gamma_correct(red[i], gamma), + 255 * gamma_correct(green[i], gamma), + 255 * gamma_correct(blue[i], gamma)); + } + ws2801_commit(); + } else { + for(i = 0; i < num_modules; i++) { + ws2801_set_color(i, + 255 * gamma_correct(red[i], gamma), + 255 * gamma_correct(green[i], gamma), + 255 * gamma_correct(blue[i], gamma)); + } + ws2801_commit(); } - maxBlueEnergy *= COLOR_MAX_REDUCTION_FACTOR; - if(curBlueEnergy > maxBlueEnergy) { - maxBlueEnergy = curBlueEnergy; - } - - colorBuf[CENTER_POS][0] = 255 * gamma_correct(curRedEnergy / maxRedEnergy); - colorBuf[CENTER_POS][1] = 255 * gamma_correct(curGreenEnergy / maxGreenEnergy); - colorBuf[CENTER_POS][2] = 255 * gamma_correct(curBlueEnergy / maxBlueEnergy); - - /* - show_status(curRedEnergy, maxRedEnergy, curGreenEnergy, maxGreenEnergy, - curBlueEnergy, maxBlueEnergy); - */ - - for(i = 0; i < NUM_MODULES; i++) { - ws2801_set_color(i, - weighted_avg(colorBuf, 0, 2 * i + 1), - weighted_avg(colorBuf, 1, 2 * i + 1), - weighted_avg(colorBuf, 2, 2 * i + 1)); - } - ws2801_commit(); - if(lastUpdateTime < nextFrame - 1) { printf("Idle for 1 second -> stopping updates.\n"); - for(i = 0; i < NUM_MODULES; i++) { + for(i = 0; i < num_modules; i++) { ws2801_fade_color(i, 20, 20, 20); } ws2801_commit(); @@ -257,7 +266,14 @@ int main(int argc, char **argv) { ws2801_shutdown(); + // free arrays + free(red); + free(green); + free(blue); + pthread_join(fftThread, NULL); + lua_close(L); + return 0; } diff --git a/pulsetunnel.lua b/pulsetunnel.lua new file mode 100644 index 0000000..b2b1ccd --- /dev/null +++ b/pulsetunnel.lua @@ -0,0 +1,70 @@ +COOLDOWN_FACTOR = 0.9998 + +num_modules = 20 +center_module = 10 + +-- maximum energy values for each band +maxRedEnergy = 1 +maxGreenEnergy = 1 +maxBlueEnergy = 1 + +-- output color buffers +red = {} +green = {} +blue = {} + +function periodic() + local redEnergy = get_energy_in_band(0, 400); + local greenEnergy = get_energy_in_band(400, 4000); + local blueEnergy = get_energy_in_band(4000, 22000); + + maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR + if redEnergy > maxRedEnergy then + maxRedEnergy = redEnergy + end + + maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR + if greenEnergy > maxGreenEnergy then + maxGreenEnergy = greenEnergy + end + + maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR + if blueEnergy > maxBlueEnergy then + maxBlueEnergy = blueEnergy + end + + -- move the color buffers on by one in each direction + for i = 2,center_module,1 do + red[i-1] = red[i] + green[i-1] = green[i] + blue[i-1] = blue[i] + end + + for i = num_modules-1,center_module,-1 do + red[i+1] = red[i] + green[i+1] = green[i] + blue[i+1] = blue[i] + end + + -- set the new value for the center module + red[center_module] = redEnergy / maxRedEnergy + green[center_module] = greenEnergy / maxGreenEnergy + blue[center_module] = blueEnergy / maxBlueEnergy + + -- return the 3 color arrays + return red, green, blue +end + +function init(nmod, cmod) + num_modules = nmod + center_module = cmod + + for i = 1,nmod do + red[i] = 0 + green[i] = 0 + blue[i] = 0 + end + + -- don't use fading + return 0 +end diff --git a/run_alsa.sh b/run_alsa.sh index e8fee4e..660f12d 100755 --- a/run_alsa.sh +++ b/run_alsa.sh @@ -1,3 +1,3 @@ #!/bin/sh -arecord -c 1 -f s16 -r 22050 | ./rtfft +arecord -c 1 -f s16 -r 22050 | ./musiclight2 $* diff --git a/run_mpd.sh b/run_mpd.sh index d63ebd7..246cdae 100755 --- a/run_mpd.sh +++ b/run_mpd.sh @@ -1,4 +1,4 @@ #!/bin/sh #dd if=/tmp/mpd.fifo bs=1024 | ./musiclight2 -./musiclight2 < /tmp/mpd.fifo +./musiclight2 $* < /tmp/mpd.fifo diff --git a/run_pa.sh b/run_pa.sh index 1120439..de5990c 100755 --- a/run_pa.sh +++ b/run_pa.sh @@ -5,12 +5,12 @@ case $1 in mic) #mikro - parec -d "alsa_input.pci-0000_00_1b.0.analog-stereo" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 + parec -d "alsa_input.pci-0000_00_1b.0.analog-stereo" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 $* ;; *) # soundkarte - parec -d "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 + parec -d "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 $* ;; esac diff --git a/run_remote.sh b/run_remote.sh index e5204cc..cbc98bc 100755 --- a/run_remote.sh +++ b/run_remote.sh @@ -1,3 +1,3 @@ #!/bin/sh -nc -l -p 12345 | ./musiclight2 +nc -l -p 12345 | ./musiclight2 $* diff --git a/vumeter.lua b/vumeter.lua new file mode 100644 index 0000000..f368c2d --- /dev/null +++ b/vumeter.lua @@ -0,0 +1,85 @@ +COOLDOWN_FACTOR = 0.9998 +FACTOR = 0.2 + +num_modules = 20 +center_module = 10 + +-- maximum energy values for each band +maxRedEnergy = 1 +maxGreenEnergy = 1 +maxBlueEnergy = 1 +maxRMS = 1 + +-- output color buffers +red = {} +green = {} +blue = {} + +function periodic() + local redEnergy = get_energy_in_band(0, 400); + local greenEnergy = get_energy_in_band(400, 4000); + local blueEnergy = get_energy_in_band(4000, 22000); + local rms = get_rms(); + + maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR + if redEnergy > maxRedEnergy then + maxRedEnergy = redEnergy + end + + maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR + if greenEnergy > maxGreenEnergy then + maxGreenEnergy = greenEnergy + end + + maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR + if blueEnergy > maxBlueEnergy then + maxBlueEnergy = blueEnergy + end + + maxRMS = maxRMS * COOLDOWN_FACTOR + if rms > maxRMS then + maxRMS = rms + end + + local brightness = rms / maxRMS + + for i = 1,num_modules do + if i <= num_modules * redEnergy / maxRedEnergy then + redTarget = brightness + else + redTarget = 0 + end + red[i] = (1 - FACTOR) * red[i] + FACTOR * redTarget; + + if i <= num_modules * greenEnergy / maxGreenEnergy then + greenTarget = brightness + else + greenTarget = 0 + end + green[i] = (1 - FACTOR) * green[i] + FACTOR * greenTarget; + + if i <= num_modules * blueEnergy / maxBlueEnergy then + blueTarget = brightness + else + blueTarget = 0 + end + blue[i] = (1 - FACTOR) * blue[i] + FACTOR * blueTarget; + end + + -- return the 3 color arrays + return red, green, blue +end + +function init(nmod, cmod) + num_modules = nmod + center_module = cmod + + for i = 1,nmod do + red[i] = 0 + green[i] = 0 + blue[i] = 0 + end + + -- fadestep (0 = no fading) + return 0 +end diff --git a/ws2801.c b/ws2801.c index a0026ab..03c548a 100644 --- a/ws2801.c +++ b/ws2801.c @@ -32,7 +32,7 @@ struct WS2801Packet packetQueue[50]; int queueIndex = 0; // creates the socket needed for steering the LED strip -int ws2801_init(char *host, unsigned short port) { +int ws2801_init(const char *host, unsigned short port) { struct addrinfo hints; struct addrinfo *result; char portstr[6]; diff --git a/ws2801.h b/ws2801.h index cb310e9..24ef5c2 100644 --- a/ws2801.h +++ b/ws2801.h @@ -10,7 +10,7 @@ #ifndef WS2801_H #define WS2801_H -int ws2801_init(char *host, unsigned short port); +int ws2801_init(const char *host, unsigned short port); void ws2801_set_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b); void ws2801_fade_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b); void ws2801_add_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);