summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/channel.c27
-rw-r--r--src/channel.h10
-rw-r--r--src/channel.test.c75
-rw-r--r--src/mossrose.c22
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();