Index mux inputs by an integer
This commit is contained in:
parent
c72f71e61e
commit
fe6db823a7
137
src/emu/mux.c
137
src/emu/mux.c
@ -5,23 +5,28 @@
|
|||||||
static int
|
static int
|
||||||
default_select(struct mux *mux,
|
default_select(struct mux *mux,
|
||||||
struct value key,
|
struct value key,
|
||||||
struct mux_input **input)
|
struct mux_input **pinput)
|
||||||
{
|
{
|
||||||
if (value_is_null(key)) {
|
if (key.type == VALUE_NULL) {
|
||||||
*input = NULL;
|
*pinput = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mux_input *tmp = mux_find_input(mux, key);
|
if (key.type != VALUE_INT64) {
|
||||||
|
err("only null and int64 values supported");
|
||||||
if (tmp == NULL) {
|
|
||||||
char buf[128];
|
|
||||||
err("default_select: cannot find input with key %s\n",
|
|
||||||
value_str(key, buf));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*input = tmp;
|
int64_t index = key.i;
|
||||||
|
|
||||||
|
if (index < 0 || index >= mux->ninputs) {
|
||||||
|
err("index out of bounds %ld", index);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mux_input *input = &mux->inputs[index];
|
||||||
|
|
||||||
|
*pinput = input;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -31,11 +36,13 @@ select_input(struct mux *mux,
|
|||||||
struct value key,
|
struct value key,
|
||||||
struct mux_input **input)
|
struct mux_input **input)
|
||||||
{
|
{
|
||||||
if (mux->select_func == NULL)
|
if (mux->select_func == NULL) {
|
||||||
die("select_input: select_func is NULL\n");
|
if (default_select(mux, key, input) != 0) {
|
||||||
|
err("default_select failed\n");
|
||||||
if (mux->select_func(mux, key, input) != 0) {
|
return -1;
|
||||||
err("select_input: select_func failed\n");
|
}
|
||||||
|
} else if (mux->select_func(mux, key, input) != 0) {
|
||||||
|
err("select_func failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +63,14 @@ cb_select(struct chan *sel_chan, void *ptr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear previous selected input */
|
||||||
|
if (mux->selected >= 0) {
|
||||||
|
struct mux_input *old_input = &mux->inputs[mux->selected];
|
||||||
|
bay_disable_cb(old_input->cb);
|
||||||
|
old_input->selected = 0;
|
||||||
|
mux->selected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
char buf[128];
|
char buf[128];
|
||||||
UNUSED(buf);
|
UNUSED(buf);
|
||||||
dbg("select channel got value %s\n",
|
dbg("select channel got value %s\n",
|
||||||
@ -63,11 +78,14 @@ cb_select(struct chan *sel_chan, void *ptr)
|
|||||||
|
|
||||||
struct mux_input *input = NULL;
|
struct mux_input *input = NULL;
|
||||||
if (select_input(mux, sel_value, &input) != 0) {
|
if (select_input(mux, sel_value, &input) != 0) {
|
||||||
err("cb_select: select_input failed\n");
|
err("select_input failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input) {
|
if (input) {
|
||||||
|
bay_enable_cb(input->cb);
|
||||||
|
input->selected = 1;
|
||||||
|
mux->selected = input->index;
|
||||||
dbg("mux selects input key=%s chan=%s\n",
|
dbg("mux selects input key=%s chan=%s\n",
|
||||||
value_str(sel_value, buf), input->chan->name);
|
value_str(sel_value, buf), input->chan->name);
|
||||||
}
|
}
|
||||||
@ -87,38 +105,18 @@ cb_select(struct chan *sel_chan, void *ptr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when the input channel changes its value */
|
/** Called when the input channel changes its value and is selected */
|
||||||
static int
|
static int
|
||||||
cb_input(struct chan *in_chan, void *ptr)
|
cb_input(struct chan *in_chan, void *ptr)
|
||||||
{
|
{
|
||||||
struct mux *mux = ptr;
|
struct mux_input *input = ptr;
|
||||||
|
|
||||||
struct value sel_value;
|
dbg("selected mux input %s changed", in_chan->name);
|
||||||
if (chan_read(mux->select, &sel_value) != 0) {
|
|
||||||
err("cb_input: chan_read(select) failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mux_input *input = NULL;
|
struct value out_value;
|
||||||
if (select_input(mux, sel_value, &input) != 0) {
|
|
||||||
err("cb_input: select_input failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Nothing to do, the input is not selected */
|
|
||||||
if (input == NULL || input->chan != in_chan) {
|
|
||||||
//dbg("input channel %s changed but not selected\n",
|
|
||||||
// in_chan->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg("selected mux input %s changed\n", in_chan->name);
|
|
||||||
|
|
||||||
/* Set to null by default */
|
|
||||||
struct value out_value = value_null();
|
|
||||||
|
|
||||||
if (chan_read(in_chan, &out_value) != 0) {
|
if (chan_read(in_chan, &out_value) != 0) {
|
||||||
err("cb_input: chan_read() failed\n");
|
err("chan_read() failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +125,8 @@ cb_input(struct chan *in_chan, void *ptr)
|
|||||||
dbg("setting output chan %s to value %s",
|
dbg("setting output chan %s to value %s",
|
||||||
mux->output->name, value_str(out_value, buf));
|
mux->output->name, value_str(out_value, buf));
|
||||||
|
|
||||||
if (chan_set(mux->output, out_value) != 0) {
|
if (chan_set(input->output, out_value) != 0) {
|
||||||
err("cb_input: chan_set() failed\n");
|
err("chan_set() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +138,8 @@ mux_init(struct mux *mux,
|
|||||||
struct bay *bay,
|
struct bay *bay,
|
||||||
struct chan *select,
|
struct chan *select,
|
||||||
struct chan *output,
|
struct chan *output,
|
||||||
mux_select_func_t select_func)
|
mux_select_func_t select_func,
|
||||||
|
int64_t ninputs)
|
||||||
{
|
{
|
||||||
if (chan_get_type(output) != CHAN_SINGLE) {
|
if (chan_get_type(output) != CHAN_SINGLE) {
|
||||||
err("mux_init: output channel must be of type single\n");
|
err("mux_init: output channel must be of type single\n");
|
||||||
@ -176,15 +175,20 @@ mux_init(struct mux *mux,
|
|||||||
memset(mux, 0, sizeof(struct mux));
|
memset(mux, 0, sizeof(struct mux));
|
||||||
mux->select = select;
|
mux->select = select;
|
||||||
mux->output = output;
|
mux->output = output;
|
||||||
|
mux->ninputs = ninputs;
|
||||||
|
mux->inputs = calloc(ninputs, sizeof(struct mux_input));
|
||||||
|
|
||||||
if (select_func == NULL)
|
if (mux->inputs == NULL) {
|
||||||
select_func = default_select;
|
err("calloc failed:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
mux->select_func = select_func;
|
mux->select_func = select_func;
|
||||||
mux->bay = bay;
|
mux->bay = bay;
|
||||||
|
|
||||||
if (bay_add_cb(bay, BAY_CB_DIRTY, select, cb_select, mux) != 0) {
|
/* Select always enabled */
|
||||||
err("mux_init: bay_add_cb failed\n");
|
if (bay_add_cb(bay, BAY_CB_DIRTY, select, cb_select, mux, 1) == NULL) {
|
||||||
|
err("bay_add_cb failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,16 +196,13 @@ mux_init(struct mux *mux,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct mux_input *
|
struct mux_input *
|
||||||
mux_find_input(struct mux *mux, struct value value)
|
mux_get_input(struct mux *mux, int64_t index)
|
||||||
{
|
{
|
||||||
struct mux_input *input = NULL;
|
return &mux->inputs[index];
|
||||||
|
|
||||||
HASH_FIND(hh, mux->input, &value, sizeof(value), input);
|
|
||||||
return input;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
mux_add_input(struct mux *mux, struct value key, struct chan *chan)
|
mux_set_input(struct mux *mux, int64_t index, struct chan *chan)
|
||||||
{
|
{
|
||||||
if (chan == mux->output) {
|
if (chan == mux->output) {
|
||||||
err("mux_init: cannot use same input channel as output\n");
|
err("mux_init: cannot use same input channel as output\n");
|
||||||
@ -213,31 +214,23 @@ mux_add_input(struct mux *mux, struct value key, struct chan *chan)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mux_find_input(mux, key) != NULL) {
|
struct mux_input *input = &mux->inputs[index];
|
||||||
char buf[128];
|
|
||||||
err("mux_add_input: input key %s already in mux\n",
|
if (input->chan != NULL) {
|
||||||
value_str(key, buf));
|
err("input %d already has a channel", index);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mux_input *input = calloc(1, sizeof(struct mux_input));
|
input->index = index;
|
||||||
|
|
||||||
if (input == NULL) {
|
|
||||||
err("mux_add_input: calloc failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
input->key = key;
|
|
||||||
input->chan = chan;
|
input->chan = chan;
|
||||||
|
input->output = mux->output;
|
||||||
|
|
||||||
HASH_ADD_KEYPTR(hh, mux->input, &input->key, sizeof(input->key), input);
|
/* Inputs disabled until selected */
|
||||||
|
input->cb = bay_add_cb(mux->bay, BAY_CB_DIRTY, chan, cb_input, input, 0);
|
||||||
if (bay_add_cb(mux->bay, BAY_CB_DIRTY, chan, cb_input, mux) != 0) {
|
if (input->cb == NULL) {
|
||||||
err("mux_add_input: bay_add_cb failed\n");
|
err("bay_add_cb failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mux->ninputs++;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,16 @@
|
|||||||
#include "bay.h"
|
#include "bay.h"
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
struct mux_input {
|
|
||||||
struct value key;
|
|
||||||
struct chan *chan;
|
|
||||||
UT_hash_handle hh;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mux;
|
struct mux;
|
||||||
|
|
||||||
|
struct mux_input {
|
||||||
|
int64_t index;
|
||||||
|
struct chan *chan;
|
||||||
|
int selected;
|
||||||
|
struct chan *output;
|
||||||
|
struct bay_cb *cb;
|
||||||
|
};
|
||||||
|
|
||||||
typedef int (* mux_select_func_t)(struct mux *mux,
|
typedef int (* mux_select_func_t)(struct mux *mux,
|
||||||
struct value value,
|
struct value value,
|
||||||
struct mux_input **input);
|
struct mux_input **input);
|
||||||
@ -20,7 +22,8 @@ typedef int (* mux_select_func_t)(struct mux *mux,
|
|||||||
struct mux {
|
struct mux {
|
||||||
struct bay *bay;
|
struct bay *bay;
|
||||||
int64_t ninputs;
|
int64_t ninputs;
|
||||||
struct mux_input *input;
|
int64_t selected;
|
||||||
|
struct mux_input *inputs;
|
||||||
mux_select_func_t select_func;
|
mux_select_func_t select_func;
|
||||||
struct chan *select;
|
struct chan *select;
|
||||||
struct chan *output;
|
struct chan *output;
|
||||||
@ -34,16 +37,16 @@ USE_RET int mux_init(struct mux *mux,
|
|||||||
struct bay *bay,
|
struct bay *bay,
|
||||||
struct chan *select,
|
struct chan *select,
|
||||||
struct chan *output,
|
struct chan *output,
|
||||||
mux_select_func_t select_func);
|
mux_select_func_t select_func,
|
||||||
|
int64_t ninputs);
|
||||||
|
|
||||||
USE_RET struct mux_input *mux_find_input(struct mux *mux,
|
USE_RET int mux_set_input(struct mux *mux,
|
||||||
struct value key);
|
int64_t index,
|
||||||
|
|
||||||
/* TODO: use an index to select the input in O(1) */
|
|
||||||
USE_RET int mux_add_input(struct mux *mux,
|
|
||||||
struct value key,
|
|
||||||
struct chan *input);
|
struct chan *input);
|
||||||
|
|
||||||
|
USE_RET struct mux_input *mux_get_input(struct mux *mux,
|
||||||
|
int64_t index);
|
||||||
|
|
||||||
USE_RET int mux_register(struct mux *mux,
|
USE_RET int mux_register(struct mux *mux,
|
||||||
struct bay *bay);
|
struct bay *bay);
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ test_input(struct mux *mux, int key)
|
|||||||
int new_value = 2000 + key;
|
int new_value = 2000 + key;
|
||||||
|
|
||||||
/* Then change that channel */
|
/* Then change that channel */
|
||||||
struct mux_input *mi = mux_find_input(mux, value_int64(key));
|
struct mux_input *mi = mux_get_input(mux, key);
|
||||||
if (mi == NULL)
|
if (mi == NULL)
|
||||||
die("mux_find_input failed to locate input %d\n", key);
|
die("mux_get_input failed to locate input %d\n", key);
|
||||||
|
|
||||||
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
||||||
die("chan_set failed\n");
|
die("chan_set failed\n");
|
||||||
@ -102,9 +102,9 @@ test_select_and_input(struct mux *mux, int key)
|
|||||||
int new_value = 2000 + key;
|
int new_value = 2000 + key;
|
||||||
|
|
||||||
/* Also change that channel */
|
/* Also change that channel */
|
||||||
struct mux_input *mi = mux_find_input(mux, value_int64(key));
|
struct mux_input *mi = mux_get_input(mux, key);
|
||||||
if (mi == NULL)
|
if (mi == NULL)
|
||||||
die("mux_find_input failed to locate input %d\n", key);
|
die("mux_get_input failed to locate input %d\n", key);
|
||||||
|
|
||||||
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
||||||
die("chan_set failed\n");
|
die("chan_set failed\n");
|
||||||
@ -122,9 +122,9 @@ test_input_and_select(struct mux *mux, int key)
|
|||||||
int new_value = 2000 + key;
|
int new_value = 2000 + key;
|
||||||
|
|
||||||
/* First change the input */
|
/* First change the input */
|
||||||
struct mux_input *mi = mux_find_input(mux, value_int64(key));
|
struct mux_input *mi = mux_get_input(mux, key);
|
||||||
if (mi == NULL)
|
if (mi == NULL)
|
||||||
die("mux_find_input failed to locate input %d\n", key);
|
die("mux_get_input failed to locate input %d\n", key);
|
||||||
|
|
||||||
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
||||||
die("chan_set failed\n");
|
die("chan_set failed\n");
|
||||||
@ -145,9 +145,9 @@ test_mid_propagate(struct mux *mux, int key)
|
|||||||
{
|
{
|
||||||
int new_value = 2000 + key;
|
int new_value = 2000 + key;
|
||||||
|
|
||||||
struct mux_input *mi = mux_find_input(mux, value_int64(key));
|
struct mux_input *mi = mux_get_input(mux, key);
|
||||||
if (mi == NULL)
|
if (mi == NULL)
|
||||||
die("mux_find_input failed to locate input %d\n", key);
|
die("mux_get_input failed to locate input %d\n", key);
|
||||||
|
|
||||||
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
if (chan_set(mi->chan, value_int64(new_value)) != 0)
|
||||||
die("chan_set failed\n");
|
die("chan_set failed\n");
|
||||||
@ -169,13 +169,13 @@ test_duplicate_output(struct mux *mux, int key1, int key2)
|
|||||||
{
|
{
|
||||||
int new_value = 2000 + key1;
|
int new_value = 2000 + key1;
|
||||||
|
|
||||||
struct mux_input *in1 = mux_find_input(mux, value_int64(key1));
|
struct mux_input *in1 = mux_get_input(mux, key1);
|
||||||
if (in1 == NULL)
|
if (in1 == NULL)
|
||||||
die("mux_find_input failed to locate input1 %d\n", key1);
|
die("mux_get_input failed to locate input1 %d\n", key1);
|
||||||
|
|
||||||
struct mux_input *in2 = mux_find_input(mux, value_int64(key2));
|
struct mux_input *in2 = mux_get_input(mux, key2);
|
||||||
if (in2 == NULL)
|
if (in2 == NULL)
|
||||||
die("mux_find_input failed to locate input2 %d\n", key2);
|
die("mux_get_input failed to locate input2 %d\n", key2);
|
||||||
|
|
||||||
if (chan_set(in1->chan, value_int64(new_value)) != 0)
|
if (chan_set(in1->chan, value_int64(new_value)) != 0)
|
||||||
die("chan_set failed\n");
|
die("chan_set failed\n");
|
||||||
@ -233,17 +233,17 @@ main(void)
|
|||||||
|
|
||||||
struct mux mux;
|
struct mux mux;
|
||||||
/* Attempt to init the mux without registering the output */
|
/* Attempt to init the mux without registering the output */
|
||||||
if (mux_init(&mux, &bay, &select, &output, NULL) == 0)
|
if (mux_init(&mux, &bay, &select, &output, NULL, N) == 0)
|
||||||
die("mux_init didn't fail\n");
|
die("mux_init didn't fail\n");
|
||||||
|
|
||||||
if (bay_register(&bay, &output) != 0)
|
if (bay_register(&bay, &output) != 0)
|
||||||
die("bay_register failed\n");
|
die("bay_register failed\n");
|
||||||
|
|
||||||
if (mux_init(&mux, &bay, &select, &output, NULL) != 0)
|
if (mux_init(&mux, &bay, &select, &output, NULL, N) != 0)
|
||||||
die("mux_init failed\n");
|
die("mux_init failed\n");
|
||||||
|
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
if (mux_add_input(&mux, value_int64(i), &inputs[i]) != 0)
|
if (mux_set_input(&mux, i, &inputs[i]) != 0)
|
||||||
die("mux_add_input failed\n");
|
die("mux_add_input failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user