diff options
author | sanine <sanine.not@pm.me> | 2022-09-04 00:39:24 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-09-04 00:39:24 -0500 |
commit | 63db9380f84cb3eb35d2de430b0783afa5773e85 (patch) | |
tree | ffc8360c7bc7e670768cbadcf79597c03b9434a2 /src | |
parent | ac48f807cb85423a8063795e3320fedde1ddf5c1 (diff) |
implement callbacks
Diffstat (limited to 'src')
-rw-r--r-- | src/channel.c | 27 | ||||
-rw-r--r-- | src/channel.h | 10 | ||||
-rw-r--r-- | src/channel.test.c | 75 | ||||
-rw-r--r-- | src/mossrose.c | 22 |
4 files changed, 134 insertions, 0 deletions
diff --git a/src/channel.c b/src/channel.c index 8615265..ac955a1 100644 --- a/src/channel.c +++ b/src/channel.c @@ -15,16 +15,24 @@ void channel_init(struct channel_t *chan) chan->shared.volume = 255; chan->shared.pan_left = -128; chan->shared.pan_right = 128; + chan->shared.trigger_callback = 0; chan->sound_mutex = p_mutex_new(); chan->sound.left = NULL; chan->sound.right = NULL; chan->pos = 0; + + chan->callback = NULL; + chan->userdata = NULL; } void channel_reset(struct channel_t *chan) { + p_atomic_int_inc(&(chan->shared.trigger_callback)); + if (p_atomic_int_get(&(chan->shared.trigger_callback)) > 32000) + /* prevent integer overflow */ + p_atomic_int_set(&(chan->shared.trigger_callback), 1); chan->pos = 0; int loops = channel_atomic_get(chan->shared.loops); if (loops) { @@ -68,6 +76,25 @@ void channel_set_pan(struct channel_t *chan, float pan_left, float pan_right) } +void channel_set_callback(struct channel_t *chan, channel_callback_t callback, void *userdata) +{ + channel_atomic_set(chan->shared.trigger_callback, 0); + chan->callback = callback; + chan->userdata = userdata; +} + + +void channel_poll_callbacks(struct channel_t *chan, int index) +{ + int trigger_callback = channel_atomic_get(chan->shared.trigger_callback); + while (trigger_callback) { + if (chan->callback != NULL) chan->callback(index, chan->userdata); + trigger_callback -= 1; + } + channel_atomic_set(chan->shared.trigger_callback, 0); +} + + int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, bool force, int loops) { if (!force && channel_atomic_get(chan->shared.active)) diff --git a/src/channel.h b/src/channel.h index 5be42a2..61a1c7d 100644 --- a/src/channel.h +++ b/src/channel.h @@ -7,6 +7,9 @@ #include <mossrose.h> +typedef void (*channel_callback_t)(int channel, void *userdata); + + struct channel_shared_t { volatile pint active; /* boolean */ volatile pint paused; /* boolean */ @@ -14,6 +17,7 @@ struct channel_shared_t { volatile pint pan_left; /* -255-255 */ volatile pint pan_right; /* -255-255 */ volatile pint loops; + volatile pint trigger_callback; }; @@ -26,6 +30,9 @@ struct channel_t { PMutex *sound_mutex; struct mossrose_sound_t sound; size_t pos; + + channel_callback_t callback; + void *userdata; }; @@ -35,7 +42,10 @@ void channel_pause(struct channel_t *chan); void channel_resume(struct channel_t *chan); void channel_set_volume(struct channel_t *chan, float volume); void channel_set_pan(struct channel_t *chan, float pan_left, float pan_right); +void channel_set_callback(struct channel_t *chan, channel_callback_t callback, void *userdata); +void channel_poll_callbacks(struct channel_t *chan, int index); int channel_sound_load(struct channel_t *chan, struct mossrose_sound_t *sound, bool force, int loops); +void channel_update_shared(struct channel_t *chan); void channel_get_next_sample(float *left, float *right, struct channel_t *chan); diff --git a/src/channel.test.c b/src/channel.test.c index 067879f..1b07350 100644 --- a/src/channel.test.c +++ b/src/channel.test.c @@ -68,6 +68,9 @@ void test_channel_init() lily_assert_null(chan.sound.left); lily_assert_null(chan.sound.right); lily_assert_int_equal(chan.pos, 0); + + lily_assert_null(chan.callback); + lily_assert_null(chan.userdata); } @@ -76,10 +79,12 @@ void test_channel_reset_last_loop() struct channel_t chan; chan.shared.active = true; chan.shared.loops = 1; + chan.shared.trigger_callback = 0; channel_reset(&chan); lily_assert_int_equal(chan.shared.active, false); + lily_assert_int_equal(chan.shared.trigger_callback, 1); } @@ -113,6 +118,19 @@ void test_channel_reset_infinite_loop() } +void test_channel_reset_trigger_callback() +{ + struct channel_t chan; + chan.shared.active = true; + chan.shared.loops = 1; + chan.shared.trigger_callback = 0; + + channel_reset(&chan); + + lily_assert_int_equal(chan.shared.trigger_callback, 1); +} + + void test_channel_pause() { struct channel_t chan; @@ -187,6 +205,59 @@ void test_channel_set_pan() } +void test_cb(int c, void *d) {} + +void test_channel_set_callback() +{ + struct channel_t chan; + chan.callback = NULL; + chan.userdata = NULL; + chan.shared.trigger_callback = 15; + + channel_set_callback(&chan, test_cb, &chan); + + lily_assert_int_equal(chan.shared.trigger_callback, 0); + lily_assert_ptr_equal(chan.callback, test_cb); + lily_assert_ptr_equal(chan.userdata, &chan); +} + + +void test_cb2(int c, void *d) +{ + int *x = d; + *x += 1; +} + +void test_channel_poll_callbacks() +{ + struct channel_t chan; + chan.callback = test_cb2; + int x = 0; + chan.userdata = &x; + chan.shared.trigger_callback = 5; + + channel_poll_callbacks(&chan, 0); + + lily_assert_int_equal(x, 5); + lily_assert_int_equal(chan.shared.trigger_callback, 0); +} + + +void test_channel_poll_callbacks_none() +{ + struct channel_t chan; + chan.callback = test_cb2; + int x = 0; + chan.userdata = &x; + chan.shared.trigger_callback = 0; + + channel_poll_callbacks(&chan, 0); + + lily_assert_int_equal(x, 0); + lily_assert_int_equal(chan.shared.trigger_callback, 0); +} + + void test_channel_sound_load() { lily_mock_use(&mock_p_mutex_lock); @@ -677,6 +748,7 @@ void suite_channel() lily_run_test(test_channel_reset_last_loop); lily_run_test(test_channel_reset_penultimate_loop); lily_run_test(test_channel_reset_infinite_loop); + lily_run_test(test_channel_reset_trigger_callback); lily_run_test(test_channel_sound_load); lily_run_test(test_channel_sound_load_mono); @@ -692,6 +764,9 @@ void suite_channel() lily_run_test(test_channel_get_next_sample_mono_panned); lily_run_test(test_channel_get_next_sample_panned); + lily_run_test(test_channel_poll_callbacks); + lily_run_test(test_channel_poll_callbacks_none); + lily_mock_destroy(mock_p_mutex_new); lily_mock_destroy(mock_p_mutex_trylock); lily_mock_destroy(mock_p_mutex_unlock); diff --git a/src/mossrose.c b/src/mossrose.c index cd1b98d..2e27c45 100644 --- a/src/mossrose.c +++ b/src/mossrose.c @@ -4,6 +4,7 @@ #include <portaudio.h> #include <mossrose.h> #include "channel.h" +#include "sound.h" struct mossrose_global_t { @@ -131,8 +132,29 @@ void mossrose_channel_resume(int channel) { } +void mossrose_channel_set_callback(int channel, channel_callback_t callback, void *userdata) +{ + struct channel_t *chan = mossrose_global.channels + channel; + channel_set_callback(chan, callback, userdata); +} + + +void mossrose_poll_callbacks() +{ + for (int i=0; i<mossrose_global.n_channels; i++) { + struct channel_t *chan = mossrose_global.channels + i; + channel_poll_callbacks(chan, i); + } +} + + int mossrose_terminate() { + for (int i=0; i<mossrose_global.n_channels; i++) { + sound_free_audio(&(mossrose_global.channels[i].sound)); + } + free(mossrose_global.channels); + Pa_AbortStream(mossrose_global.stream); Pa_CloseStream(mossrose_global.stream); Pa_Terminate(); |