summaryrefslogtreecommitdiff
path: root/src/fruits/sink
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-01-06 19:54:21 -0500
committerAndrew Opalach <andrew@akon.city> 2024-01-06 19:54:21 -0500
commite6c1c0afc69ee13465bb68a6bdeb35b6876146d4 (patch)
treeffea140be35691dfc24e9a6ca6c54e2d0247e8a8 /src/fruits/sink
parent11bbaf5198d15da44731ffb63411558f1c72f97e (diff)
downloadcamu-e6c1c0afc69ee13465bb68a6bdeb35b6876146d4.tar.gz
camu-e6c1c0afc69ee13465bb68a6bdeb35b6876146d4.tar.bz2
camu-e6c1c0afc69ee13465bb68a6bdeb35b6876146d4.zip
Initial synced playback
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/fruits/sink')
-rw-r--r--src/fruits/sink/meson.build10
-rw-r--r--src/fruits/sink/sink.c201
2 files changed, 211 insertions, 0 deletions
diff --git a/src/fruits/sink/meson.build b/src/fruits/sink/meson.build
new file mode 100644
index 0000000..c409857
--- /dev/null
+++ b/src/fruits/sink/meson.build
@@ -0,0 +1,10 @@
+sink_src = ['sink.c']
+sink_deps = [common_deps, buffer, cache, av, screen, render, mixer, libsink]
+
+use_tui = false
+if use_tui
+ sink_src += []
+ sink_deps += [dependency('notcurses')]
+endif
+
+executable('sink', sink_src, dependencies: sink_deps)
diff --git a/src/fruits/sink/sink.c b/src/fruits/sink/sink.c
new file mode 100644
index 0000000..d0455a4
--- /dev/null
+++ b/src/fruits/sink/sink.c
@@ -0,0 +1,201 @@
+#include <al/log.h>
+#include <aki/event_loop.h>
+
+#include "../../codec/libav/common.h"
+
+#include "../../mixer/audio_miniaudio.h"
+
+#include "../../screen/screen.h"
+#include "../../render/renderer_libplacebo.h"
+//#include "../../render/renderer_tiger.h"
+
+#include "../../libsink/sink.h"
+#include "../../tree/common.h"
+
+#include "../../shoki/src/search.h"
+
+struct cmv {
+ s32 quit;
+ struct camu_screen scr;
+ struct camu_renderer *renderer;
+ struct camu_mixer mixer;
+ struct aki_event_loop loop;
+ struct camu_sink sink;
+};
+
+static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque)
+{
+ struct cmv *c = (struct cmv *)userdata;
+ switch (op) {
+ case CAMU_SINK_ADD_BUFFER:
+ switch (type) {
+ case CAMU_SINK_AUDIO: {
+ struct camu_audio_buffer *buf = (struct camu_audio_buffer *)opaque;
+ camu_mixer_add_buffer(&c->mixer, buf);
+ al_log_debug("cmv", "Audio buffer added.");
+ break;
+ }
+ case CAMU_SINK_VIDEO: {
+ struct camu_video_buffer *buf = (struct camu_video_buffer *)opaque;
+ camu_screen_add_buffer(&c->scr, buf);
+ al_log_debug("cmv", "Video buffer added.");
+ break;
+ }
+ }
+ break;
+ case CAMU_SINK_REMOVE_BUFFER:
+ switch (type) {
+ case CAMU_SINK_AUDIO: {
+ struct camu_audio_buffer *buf = (struct camu_audio_buffer *)opaque;
+ camu_mixer_remove_buffer(&c->mixer, buf);
+ al_log_debug("cmv", "Audio buffer removed.");
+ break;
+ }
+ case CAMU_SINK_VIDEO: {
+ struct camu_video_buffer *buf = (struct camu_video_buffer *)opaque;
+ camu_screen_remove_buffer(&c->scr, buf);
+ al_log_debug("cmv", "Video buffer removed.");
+ break;
+ }
+ }
+ break;
+ case CAMU_SINK_SWAP_BUFFER:
+ switch (type) {
+ case CAMU_SINK_AUDIO: {
+ break;
+ }
+ }
+ break;
+ case CAMU_SINK_SET_BUFFERED: {
+ break;
+ }
+ case CAMU_SINK_START:
+ switch (type) {
+ case CAMU_SINK_AUDIO: {
+ camu_mixer_resume(&c->mixer);
+ al_log_debug("cmv", "Audio started.");
+ break;
+ }
+ case CAMU_SINK_VIDEO: {
+ camu_screen_set_state(&c->scr, CAMU_SCREEN_PLAYING);
+ camu_screen_wake(&c->scr);
+ al_log_debug("cmv", "Video started.");
+ break;
+ }
+ }
+ break;
+ case CAMU_SINK_STOP:
+ switch (type) {
+ case CAMU_SINK_AUDIO: {
+ camu_mixer_pause(&c->mixer);
+ al_log_debug("cmv", "Audio stopped.");
+ break;
+ }
+ case CAMU_SINK_VIDEO: {
+ camu_screen_set_state(&c->scr, CAMU_SCREEN_PAUSED);
+ al_log_debug("cmv", "Video stopped.");
+ break;
+ }
+ }
+ break;
+ case CAMU_SINK_EXIT:
+ camu_sink_close(&c->sink);
+ aki_event_loop_break(&c->loop);
+ break;
+ }
+ return CAMU_SINK_OK;
+}
+
+static void screen_callback(void *userdata, u8 op, f64 float0)
+{
+ struct cmv *c = (struct cmv *)userdata;
+ switch (op) {
+ case CAMU_SCREEN_NEXT:
+ break;
+ case CAMU_SCREEN_PREVIOUS:
+ break;
+ case CAMU_SCREEN_TOGGLE_PAUSE:
+ camu_sink_toggle_pause(&c->sink);
+ break;
+ case CAMU_SCREEN_SEEK:
+ camu_sink_seek(&c->sink, float0);
+ break;
+ case CAMU_SCREEN_CLOSE:
+ c->quit = 1;
+ break;
+ }
+}
+
+static aki_thread_result AKI_THREADCALL event_loop_thread(void *userdata)
+{
+ struct cmv *c = (struct cmv *)userdata;
+ aki_event_loop_run(&c->loop);
+ aki_event_loop_destroy(&c->loop);
+ return 0;
+}
+
+static struct cmv c = { 0 };
+
+static void sigint_handler(s32 signum)
+{
+ (void)signum;
+ c.quit = 1;
+}
+
+s32 main(s32 argc, char *argv[])
+{
+ if (!aki_common_init()) return EXIT_FAILURE;
+
+ signal(SIGINT, sigint_handler);
+
+ aki_event_loop_init(&c.loop);
+
+ c.scr.callback = screen_callback;
+ c.scr.userdata = &c;
+ if (!camu_screen_init(&c.scr) || !camu_screen_create_window(&c.scr, "cmv")) {
+ goto err;
+ }
+ c.renderer = camu_renderer_lp_create();
+ //c.renderer = camu_renderer_tiger_create();
+ if (!camu_screen_create_renderer(&c.scr, c.renderer)) {
+ goto err;
+ }
+ c.renderer->render(c.renderer, &c.scr);
+
+ camu_mixer_init(&c.mixer, (struct camu_audio *)&audio_plugin_miniaudio);
+ c.mixer.audio->configure_stream(c.mixer.audio, NULL);
+
+ camu_sink_init(&c.sink, &c.loop, &c.mixer, c.renderer);
+ c.sink.callback = sink_callback;
+ c.sink.userdata = &c;
+ camu_sink_connect(&c.sink, al_str_c("127.0.0.1"), TREE_PORT);
+
+ struct aki_thread thread0;
+ aki_thread_create(&thread0, event_loop_thread, &c);
+
+ c.quit = 0;
+
+ while (!c.quit) {
+ if (camu_screen_tick(&c.scr)) {
+ c.renderer->render(c.renderer, &c.scr);
+ }
+ }
+
+ camu_screen_set_state(&c.scr, CAMU_SCREEN_CLOSED);
+
+ camu_sink_stop(&c.sink);
+
+ aki_thread_join(&thread0);
+
+ camu_mixer_close(&c.mixer);
+ c.renderer->free(&c.renderer);
+ camu_screen_close(&c.scr);
+
+ aki_common_close();
+
+ return EXIT_SUCCESS;
+err:
+ aki_event_loop_destroy(&c.loop);
+ aki_common_close();
+ return EXIT_FAILURE;
+}