allow cascading files to be loaded, fix the filter. Improve stability of output linear. Change a bunch of IIR settings.

This commit is contained in:
cnlohr 2015-01-10 01:44:13 -05:00
parent f3d950c129
commit a377262c80
15 changed files with 227 additions and 99 deletions

View file

@ -19,6 +19,7 @@ struct DPODriver
{
int xn;
int yn;
int rot90;
int zigzag;
};
@ -29,8 +30,8 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
struct DPODriver * d = (struct DPODriver*)id;
float cw = ((float)screenx) / d->xn;
float ch = ((float)screeny) / d->yn;
float cw = ((float)(d->rot90?screeny:screenx)) / d->xn;
float ch = ((float)(d->rot90?screenx:screeny)) / d->yn;
for( y = 0; y < d->yn; y++ )
for( x = 0; x < d->xn; x++ )
@ -54,7 +55,11 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
CNFGColor( OutLEDs[index*3+0] | (OutLEDs[index*3+1] <<8)|(OutLEDs[index*3+2] <<16) );
float dx = (x) * cw;
float dy = (y) * ch;
CNFGTackRectangle( dx, dy, dx+cw+.5, dy+ch+.5 );
if( d->rot90 )
CNFGTackRectangle( dy, dx, dy+ch+.5, dx+cw+.5 );
else
CNFGTackRectangle( dx, dy, dx+cw+.5, dy+ch+.5 );
}
CNFGColor( 0xffffff );
}
@ -66,6 +71,7 @@ static void DPOParams(void * id )
d->xn = 16; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) );
d->yn = 9; RegisterValue( "lighty", PINT, &d->yn, sizeof( d->yn ) );
d->zigzag = 0; RegisterValue( "zigzag", PINT, &d->zigzag, sizeof( d->zigzag ) );
d->rot90 = 0; RegisterValue( "rot90", PINT, &d->rot90, sizeof( d->rot90 ) );
}

View file

@ -1,3 +1,6 @@
//XXX This needs to be re-worked to only output LEDs so DisplayArray can take it.
//XXX CONSIDER DUMPING
#include "outdrivers.h"
#include "notefinder.h"
#include <stdio.h>
@ -11,7 +14,7 @@
//Uses: note_amplitudes2[note] for how many lights to use.
//Uses: note_amplitudes_out[note] for how bright it should be.
#define MAX_LEDS_PER_NOTE 512
#define MAX_LEDS_PER_NOTE 1024
extern short screenx, screeny;
@ -116,7 +119,7 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
}
}
float cw = ((float)screenx) / d->xn;
/* float cw = ((float)screenx) / d->xn;
float ch = ((float)screeny) / d->yn;
for( i = 0; i < d->note_peaks; i++ )
@ -134,7 +137,24 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
CNFGDrawBox( x, y, x+cw, y+ch );
}
}*/
int led = 0;
for( i = 0; i < d->note_peaks; i++ )
{
struct LINote * l = &d->notes[i];
int j;
float sat = nf->note_amplitudes_out[i] * d->satamp;
if( sat > 1 ) sat = 1;
uint32_t color = CCtoHEX( nf->note_positions[i] / nf->freqbins, 1.0, sat );
OutLEDs[led*3+0] = color & 0xff;
OutLEDs[led*3+1] = ( color >> 8 ) & 0xff;
OutLEDs[led*3+2] = ( color >> 16 ) & 0xff;
led++;
}
}
static void DPOParams(void * id )

View file

@ -2,13 +2,16 @@ all : colorchord
RAWDRAW:=DrawFunctions.o XDriver.o
SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o
OUTS:=LEDOUTDriver.o DisplayOUTDriver.o DisplayShapeDriver.o parameters.o chash.o
OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o
#LEDOUTDriver.o DisplayOUTDriver.o
RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext
LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse
CFLAGS:=-g -Os -flto -Wall -ffast-math
EXTRALIBS:=-lusb-1.0
colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o sort.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS)
colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o sort.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o
gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS)

View file

@ -13,8 +13,6 @@
#define MAX_LEDS_PER_NOTE 512
extern short screenx, screeny;
struct LINote
{
float x, y; //In screen space.
@ -64,8 +62,8 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
{
float angle = nf->note_positions[i] / nf->freqbins * 6.28318;
// float angle = nf->enduring_note_id[i];
float cx = screenx/2;
float cy = screeny/2;
float cx = d->xn/2.0;
float cy = d->yn/2.0;
float tx = sin( angle ) * cx + cx;
float ty = cos( angle ) * cy + cy;
l->x = l->x * .9 + tx * .1;
@ -79,8 +77,8 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
else
{
srand( nf->enduring_note_id[i] );
l->x = rand()%screenx;
l->y = rand()%screenx;
l->x = rand()%d->xn;
l->y = rand()%d->yn;
}
}
@ -92,17 +90,13 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
float cw = ((float)screenx) / d->xn;
float ch = ((float)screeny) / d->yn;
int x, y;
int led = 0;
for( y = 0; y < d->yn; y++ )
for( x = 0; x < d->xn; x++ )
{
float lx = (x+.5) * cw;
float ly = (y+.5) * ch;
float kx = (x) * cw;
float ky = (y) * ch;
float lx = (x+.5);
float ly = (y+.5);
int bestmatch = -1;
float bestmatchval = 0;
@ -126,18 +120,18 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
}
}
uint32_t color = 0;
if( bestmatch != -1 )
{
float sat = nf->note_amplitudes_out[bestmatch] * d->satamp;
if( sat > 1.0 ) sat = 1.0;
CNFGColor ( CCtoHEX( nf->note_positions[bestmatch] / nf->freqbins, 1.0, sat ) );
color = CCtoHEX( nf->note_positions[bestmatch] / nf->freqbins, 1.0, sat );
}
else
{
CNFGColor ( 0 );
}
CNFGTackRectangle( kx, ky, kx+cw, ky+ch );
OutLEDs[led*3+0] = color & 0xff;
OutLEDs[led*3+1] = ( color >> 8 ) & 0xff;
OutLEDs[led*3+2] = ( color >> 16 ) & 0xff;
led++;
}
CNFGColor ( 0xffffff );
}
@ -145,20 +139,22 @@ static void DPOUpdate(void * id, struct NoteFinder*nf)
static void DPOParams(void * id )
{
struct DPODriver * d = (struct DPODriver*)id;
d->xn = 160; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) ); printf( "XN: %d\n", d->xn );
//XXX WRONG
d->xn = 160; RegisterValue( "lightx", PINT, &d->xn, sizeof( d->xn ) );
d->yn = 90; RegisterValue( "lighty", PINT, &d->yn, sizeof( d->yn ) );
d->cutoff = .01; RegisterValue( "shape_cutoff", PFLOAT, &d->cutoff, sizeof( d->cutoff ) );
d->cutoff = .01; RegisterValue( "Voronoi_cutoff", PFLOAT, &d->cutoff, sizeof( d->cutoff ) );
d->satamp = 5; RegisterValue( "satamp", PFLOAT, &d->satamp, sizeof( d->satamp ) );
d->amppow = 2.51; RegisterValue( "amppow", PFLOAT, &d->amppow, sizeof( d->amppow ) );
d->distpow = 1.5; RegisterValue( "distpow", PFLOAT, &d->distpow, sizeof( d->distpow ) );
d->from_sides = 1.5;RegisterValue( "fromsides", PINT, &d->from_sides, sizeof( d->from_sides ) );
d->from_sides = 1; RegisterValue( "fromsides", PINT, &d->from_sides, sizeof( d->from_sides ) );
d->note_peaks = 0;
}
static struct DriverInstances * DisplayShapeDriver(const char * parameters)
static struct DriverInstances * OutputVoronoi(const char * parameters)
{
struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) );
struct DPODriver * d = ret->id = malloc( sizeof( struct DPODriver ) );
@ -169,6 +165,6 @@ static struct DriverInstances * DisplayShapeDriver(const char * parameters)
return ret;
}
REGISTER_OUT_DRIVER(DisplayShapeDriver);
REGISTER_OUT_DRIVER(OutputVoronoi);

5
TODO
View file

@ -1,8 +1,11 @@
Still to do:
Try this:
* Separate "LED Selection" from "output" algorithms.
* Separate "LED Selection" from "output" algorithms. << Do this by allowing arbitrary Lights Drivers
* For light finding, pick lights off the peaks to get number of lights to use.
* For light shifting (for 1d-looping light systems) shift the centers of the notes, then vernoi between the notes.
Brenden:
* Consider running DFT on all channels and mixing results

View file

@ -251,7 +251,7 @@ void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
void CNFGTackPoly( RDPoint * points, int verts )
{
XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin );
XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, verts, Convex, CoordModeOrigin );
}
#endif

View file

@ -7,22 +7,9 @@
#Whether to limit the control loop to ~60ish FPS.
cpu_autolimit = 1
#What display output driver should be used?
displayname = DisplayShapeDriver
#Display Shape Driver parameters
fromsides = 1
lightx = 80
lighty = 45
shape_cutoff = 0.01
satamp = 5.000
amppow = 2.510
distpow = 1.500
#General GUI properties.
title = PA Test
set_screenx = 640
set_screenx = 720
set_screeny = 480
#Sound properties.
@ -41,7 +28,7 @@ sourcename = alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
##################################
# How much to amplify the incoming signal.
amplify = 2.0
amplify = 2.5
# What is the base note? I.e. the lowest note.
# Note that it won't have very much impact until an octave up though!
@ -52,29 +39,43 @@ base_hz = 55.0000
# default_sigma = 1.4000
# DFT properties for the DFT up top.
dft_iir = 0.7000
dft_q = 10.0000
dft_speedup = 300.0000
dft_iir = 0.0
dft_q = 20.0000
dft_speedup = 1000.0000
octaves = 5
filter_iter = 1
filter_strength = 0.5000
filter_iter = 2
filter_strength = .5
# How many bins per octave to use?
freqbins = 24
# For the final note information... How much to slack everything?
note_attach_amp_iir = 0.3000
note_attach_amp_iir2 = 0.2000
note_attach_amp_iir2 = 0.200
note_attach_freq_iir = 0.4000
#How many bins a note can jump from frame to frame to be considered a slide.
#this is used to prevent notes from popping in and out a lot.
note_combine_distance = 0.5000
note_jumpability = 2.5000
note_jumpability = 1.8000
note_minimum_new_distribution_value = 0.0200
note_out_chop = 0.1000
#=======================================================================
#Outputs
This is a vornoi thing:
outdrivers = DisplayArray, OutputVoronoi
lightx = 72
lighty = 48
fromsides = 1
shape_cutoff = 0.03
satamp = 5.000
amppow = 2.510
distpow = 1.500

View file

@ -2,7 +2,7 @@
#include <math.h>
#include <string.h>
/*
void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float iir )
{
int i;
@ -33,8 +33,7 @@ void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float iir )
{
folded[i] = v * iir + folded[i] * inv;
}
}
}*/
void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter )
@ -47,8 +46,10 @@ void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter )
memcpy( tmp, folded, sizeof( tmp ) );
for( i = 0; i < bins; i++ )
{
float left = tmp[(i-1+bins)%bins];
float right = tmp[(i-1+bins)%bins];
// float left = tmp[(i-1+bins)%bins];
// float right = tmp[(i-1+bins)%bins];
float right = tmp[(i+bins+1)%bins];
float left = tmp[(i+bins-1)%bins];
folded[i] = folded[i] * (1.-strength) + (left + right) * strength * 0.5;
}
}

View file

@ -3,7 +3,7 @@
//Perform a two-pass filter on the data, circularly. Once right, then left.
void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float strength );
//void FilterFoldedBinsIIRTWOPASS( float * folded, int bins, float strength );
void FilterFoldedBinsBlob( float * folded, int bins, float strength, int iter );

72
main.c
View file

@ -17,6 +17,8 @@
short screenx, screeny;
int gargc;
char ** gargv;
struct DriverInstances * outdriver[MAX_OUT_DRIVERS];
int set_screenx = 640; REGISTER_PARAM( set_screenx, PINT );
int set_screeny = 480; REGISTER_PARAM( set_screeny, PINT );
@ -68,7 +70,7 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun
//Load the samples into a ring buffer. Split the channels from interleved to one per buffer.
*samplesp = 0;
int process_channels = (MAX_CHANNELS < channelin)?MAX_CHANNELS:channelin;
// int process_channels = (MAX_CHANNELS < channelin)?MAX_CHANNELS:channelin;
int i;
int j;
@ -77,13 +79,13 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun
if( sample_channel < 0 )
{
float fo = 0;
for( j = 0; j < process_channels; j++ )
for( j = 0; j < channelin; j++ )
{
float f = in[i*channelin+j];
if( f < -1 || f > 1 ) continue;
fo += f;
}
fo /= process_channels;
fo /= channelin;
sound[soundhead] = fo;
soundhead = (soundhead+1)%SOUNDCBSIZE;
@ -144,9 +146,11 @@ void LoadFile( const char * filename )
int main(int argc, char ** argv)
{
// const char * OutDriver = "name=LEDOutDriver;leds=512;light_siding=1.9";
const char * InitialFile = "default.conf";
const char * InitialFile = 0;
const char * InitialFileDefault = "default.conf";
int i;
double LastFileTime;
double LastFileTimeInit = 0;
double LastFileTimeDefault = 0;
gargc = argc;
gargv = argv;
@ -156,8 +160,15 @@ int main(int argc, char ** argv)
InitialFile = argv[1];
}
{
LastFileTime = OGGetFileTime( InitialFile );
LastFileTimeDefault = OGGetFileTime( InitialFileDefault );
LoadFile( InitialFileDefault );
}
if( InitialFile )
{
LastFileTimeInit = OGGetFileTime( InitialFile );
LoadFile( InitialFile );
}
@ -171,7 +182,35 @@ int main(int argc, char ** argv)
CNFGBGColor = 0x800000;
CNFGDialogColor = 0x444444;
CNFGSetup( "ColorChord Test", set_screenx, set_screeny );
struct DriverInstances * outdriver = SetupOutDriver( );
char * OutDriverNames = strdup( GetParameterS( "outdrivers", "null" ) );
char * ThisDriver = OutDriverNames;
char * TDStart;
for( i = 0; i < MAX_OUT_DRIVERS; i++ )
{
while( *ThisDriver == ' ' || *ThisDriver == '\t' ) ThisDriver++;
if( !*ThisDriver ) break;
TDStart = ThisDriver;
while( *ThisDriver != 0 && *ThisDriver != ',' )
{
if( *ThisDriver == '\t' || *ThisDriver == ' ' ) *ThisDriver = 0;
ThisDriver++;
}
if( *ThisDriver )
{
*ThisDriver = 0;
ThisDriver++;
}
printf( "Loading: %s\n", TDStart );
outdriver[i] = SetupOutDriver( TDStart );
}
free(OutDriverNames);
//Initialize Sound
struct SoundDriver * sd = InitSound( sound_source, &SoundCB );
@ -198,8 +237,10 @@ int main(int argc, char ** argv)
//Done all ColorChord work.
VisTimeStart = OGGetAbsoluteTime();
if( outdriver )
outdriver->Func( outdriver->id, nf );
for( i = 0; i < MAX_OUT_DRIVERS; i++ )
if( outdriver[i] )
outdriver[i]->Func( outdriver[i]->id, nf );
VisTimeEnd = OGGetAbsoluteTime();
//Handle outputs.
@ -331,10 +372,17 @@ int main(int argc, char ** argv)
OGUSleep( (int)( SecToWait * 1000000 ) );
}
if( OGGetFileTime( InitialFile ) != LastFileTime )
if( OGGetFileTime( InitialFileDefault ) != LastFileTimeDefault ||
(InitialFile && LastFileTimeInit != OGGetFileTime( InitialFile ) ) )
{
LastFileTime = OGGetFileTime( InitialFile );
LoadFile( InitialFile );
LastFileTimeDefault = OGGetFileTime( InitialFileDefault );
LoadFile( InitialFileDefault );
if( InitialFile )
{
LastFileTimeInit = OGGetFileTime( InitialFile );
LoadFile( InitialFile );
}
}
}

View file

@ -206,6 +206,7 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head
nf->folded_bins[i] = amp;
}
//This is here to reduce the number of false-positive hits. It helps remove peaks that are meaningless.
FilterFoldedBinsBlob( nf->folded_bins, freqbins, nf->filter_strength, nf->filter_iter );
nf->FilterTime = OGGetAbsoluteTime();
@ -328,7 +329,7 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head
nf->note_amplitudes2[i] = nf->note_amplitudes2[i] * (1.-nf->note_attach_amp_iir2) + nf->note_amplitudes[i] * nf->note_attach_amp_iir2;
if( nf->note_amplitudes[i] < nf->note_min_amplitude )
if( nf->note_amplitudes2[i] < nf->note_min_amplitude )
{
nf->note_amplitudes[i] = 0;
nf->note_amplitudes2[i] = 0;

View file

@ -5,6 +5,10 @@
#include <stdio.h>
#include <stdlib.h>
unsigned char OutLEDs[MAX_LEDS*3];
int UsedLEDs;
struct OutDriverListElem ODList[MAX_OUT_DRIVERS];
const char OutDriverParameters[MAX_OUT_DRIVER_STRING];
@ -28,13 +32,12 @@ struct DriverInstances * null( )
REGISTER_OUT_DRIVER(null);
struct DriverInstances * SetupOutDriver( )
struct DriverInstances * SetupOutDriver( const char * drivername )
{
int i;
const char * p = GetParameterS( "displayname", "null" );
for( i = 0; i < MAX_OUT_DRIVERS; i++ )
{
if( ODList[i].Name && strcmp( p, ODList[i].Name ) == 0 )
if( ODList[i].Name && strcmp( drivername, ODList[i].Name ) == 0 )
{
printf( "Found: %s %p\n", ODList[i].Name, ODList[i].Init );
return ODList[i].Init( );

View file

@ -5,6 +5,12 @@
struct NoteFinder;
#define MAX_LEDS 32678
extern unsigned char OutLEDs[MAX_LEDS*3];
extern int UsedLEDs;
#define MAX_OUT_DRIVERS 64
#define MAX_OUT_DRIVER_STRING 1024

View file

@ -26,10 +26,10 @@ float GetParameterF( const char * name, float defa )
{
switch( p->t )
{
case PFLOAT: return *((float*)p->ptr);
case PINT: return *((int*)p->ptr);
case PFLOAT: return *((float*)p->lp->ptr);
case PINT: return *((int*)p->lp->ptr);
case PSTRING:
case PBUFFER: if( p->ptr ) return atof( p->ptr );
case PBUFFER: if( p->lp->ptr ) return atof( p->lp->ptr );
default: break;
}
}
@ -46,10 +46,10 @@ int GetParameterI( const char * name, int defa )
{
switch( p->t )
{
case PFLOAT: return *((float*)p->ptr);
case PINT: return *((int*)p->ptr);
case PFLOAT: return *((float*)p->lp->ptr);
case PINT: return *((int*)p->lp->ptr);
case PSTRING:
case PBUFFER: if( p->ptr ) return atoi( p->ptr );
case PBUFFER: if( p->lp->ptr ) return atoi( p->lp->ptr );
default: break;
}
}
@ -67,10 +67,10 @@ const char * GetParameterS( const char * name, const char * defa )
{
switch( p->t )
{
case PFLOAT: snprintf( returnbuffer, sizeof( returnbuffer ), "%0.4f", *((float*)p->ptr) ); return returnbuffer;
case PINT: snprintf( returnbuffer, sizeof( returnbuffer ), "%d", *((int*)p->ptr) ); return returnbuffer;
case PFLOAT: snprintf( returnbuffer, sizeof( returnbuffer ), "%0.4f", *((float*)p->lp->ptr) ); return returnbuffer;
case PINT: snprintf( returnbuffer, sizeof( returnbuffer ), "%d", *((int*)p->lp->ptr) ); return returnbuffer;
case PSTRING:
case PBUFFER: return p->ptr;
case PBUFFER: return p->lp->ptr;
default: break;
}
}
@ -83,22 +83,41 @@ const char * GetParameterS( const char * name, const char * defa )
static int SetParameter( struct Param * p, const char * str )
{
struct LinkedParameter * lp;
lp = p->lp;
switch( p->t )
{
case PFLOAT:
*((float*)p->ptr) = atof( str );
while( lp )
{
*((float*)lp->ptr) = atof( str );
lp = lp->lp;
}
break;
case PINT:
*((int*)p->ptr) = atoi( str );
while( lp )
{
*((int*)lp->ptr) = atoi( str );
lp = lp->lp;
}
break;
case PBUFFER:
strncpy( (char*)p->ptr, str, p->size );
if( p->size > 0 )
((char*)p->ptr)[p->size-1]= '\0';
while( lp )
{
strncpy( (char*)lp->ptr, str, p->size );
if( p->size > 0 )
((char*)lp->ptr)[p->size-1]= '\0';
lp = lp->lp;
}
break;
case PSTRING:
free( p->ptr );
p->ptr = strdup( str );
while( lp )
{
free( lp->ptr );
lp->ptr = strdup( str );
lp = lp->lp;
}
break;
default:
return -1;
@ -129,8 +148,8 @@ void RegisterValue( const char * name, enum ParamType t, void * ptr, int size )
{
fprintf( stderr, "Warning: Orphan parameter %s was not a PSTRING.\n", name );
}
char * orig = p->ptr;
p->ptr = ptr;
char * orig = p->lp->ptr;
p->lp->ptr = ptr;
p->t = t;
p->size = size;
p->orphan = 0;
@ -143,7 +162,18 @@ void RegisterValue( const char * name, enum ParamType t, void * ptr, int size )
}
else
{
fprintf( stderr, "Warning: Parameter %s re-registered. Cannot re-register.\n", name );
struct LinkedParameter * lp = p->lp;
if( size != p->size )
{
fprintf( stderr, "Size mismatch: Parameter %s.\n", name );
}
else
{
p->lp = malloc( sizeof( struct LinkedParameter ) );
p->lp->lp = lp;
p->lp->ptr = ptr;
memcpy( p->lp->ptr, p->lp->lp->ptr, size );
}
}
}
else
@ -151,7 +181,9 @@ void RegisterValue( const char * name, enum ParamType t, void * ptr, int size )
struct Param ** n = (struct Param**)HashTableInsert( parameters, name, 1 );
*n = malloc( sizeof( struct Param ) );
(*n)->t = t;
(*n)->ptr = ptr;
(*n)->lp = malloc( sizeof( struct LinkedParameter ) );
(*n)->lp->lp = 0;
(*n)->lp->ptr = ptr;
(*n)->orphan = 0;
(*n)->size = size;
(*n)->callback = 0;
@ -215,7 +247,9 @@ void SetParametersFromString( const char * string )
*n = malloc( sizeof ( struct Param ) );
(*n)->orphan = 1;
(*n)->t = PSTRING;
(*n)->ptr = strdup( value );
(*n)->lp = malloc( sizeof( struct LinkedParameter ) );
(*n)->lp->lp = 0;
(*n)->lp->ptr = strdup( value );
(*n)->size = strlen( value ) + 1;
(*n)->callback = 0;
}

View file

@ -22,13 +22,19 @@ struct ParamCallback
struct ParamCallback * next;
};
struct LinkedParameter
{
void * ptr;
struct LinkedParameter * lp;
};
struct Param
{
char orphan; //If this is set, then this is something that was received from a string, but has no claimed interface.
//It will be claimed when RegisterValue is called. NOTE: When orphan is set, it must be a malloc'd string.
enum ParamType t;
void * ptr;
int size;
struct LinkedParameter * lp;
struct ParamCallback * callback;
};