changeset 644:6d0f4edb79f8

core: fix music/sound and some others
author David Demelier <markand@malikania.fr>
date Sat, 23 Dec 2023 09:34:04 +0100
parents 993d9ccedcf6
children 83781cc87fca
files libmlk-core/mlk/core/js/js-music.c libmlk-core/mlk/core/js/js-music.h libmlk-core/mlk/core/js/js-sound.c libmlk-core/mlk/core/js/js-sound.h libmlk-core/mlk/core/js/js-texture.c libmlk-core/mlk/core/js/js.c libmlk-core/mlk/core/js/js.h libmlk-core/mlk/core/vfs.c
diffstat 8 files changed, 208 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/libmlk-core/mlk/core/js/js-music.c	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-music.c	Sat Dec 23 09:34:04 2023 +0100
@@ -21,10 +21,13 @@
 #include <mlk/core/alloc.h>
 #include <mlk/core/err.h>
 #include <mlk/core/music.h>
+#include <mlk/core/vfs.h>
 
 #include "js-music.h"
+#include "js.h"
 
 #define SYMBOL DUK_HIDDEN_SYMBOL("mlk::music")
+#define PROTO  DUK_HIDDEN_SYMBOL("mlk::music::proto")
 
 static struct mlk_music *
 mlk_js_music_this(duk_context *ctx)
@@ -43,28 +46,6 @@
 }
 
 static duk_ret_t
-mlk_js_music_new(duk_context *ctx)
-{
-	struct mlk_music mus;
-	const char *path;
-
-	if (!duk_is_constructor_call(ctx))
-		return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Music must be new-constructed");
-
-	path = duk_require_string(ctx, 0);
-
-	if (mlk_music_open(&mus, path) < 0)
-		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
-
-	duk_push_this(ctx);
-	duk_push_pointer(ctx, mlk_alloc_dup(&mus, 1, sizeof (mus)));
-	duk_put_prop_string(ctx, -2, SYMBOL);
-	duk_pop(ctx);
-
-	return 0;
-}
-
-static duk_ret_t
 mlk_js_music_pause(duk_context *ctx)
 {
 	mlk_music_pause(mlk_js_music_this(ctx));
@@ -118,21 +99,60 @@
 	return 0;
 }
 
+static duk_ret_t
+mlk_js_music_fromFile(duk_context *ctx)
+{
+	const char *path = duk_require_string(ctx, 0);
+	struct mlk_music mus;
+
+	if (mlk_music_open(&mus, path) < 0)
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	mlk_js_music_push(ctx, &mus);
+
+	return 1;
+}
+
+static duk_ret_t
+mlk_js_music_fromVFS(duk_context *ctx)
+{
+	const char *path = duk_require_string(ctx, 0);
+	struct mlk_vfs *vfs = mlk_js_require(ctx)->vfs;
+	struct mlk_vfs_file *file;
+	struct mlk_music mus;
+	int rv;
+
+	if (!(file = mlk_vfs_open(vfs, path, "r")))
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	rv = mlk_music_openvfs(&mus, file);
+	mlk_vfs_file_finish(file);
+
+	if (rv < 0)
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	mlk_js_music_push(ctx, &mus);
+
+	return 1;
+}
+
 static const duk_number_list_entry flags[] = {
 	{ "NONE",       MLK_MUSIC_NONE                          },
 	{ "LOOP",       MLK_MUSIC_LOOP                          },
 	{ NULL,         0                                       }
 };
 
-static const duk_function_list_entry functions[] = {
+static const duk_function_list_entry methods[] = {
 	{ "pause",      mlk_js_music_pause,     0               },
 	{ "resume",     mlk_js_music_resume,    0               },
 	{ "stop",       mlk_js_music_stop,      DUK_VARARGS     },
+	{ "play",       mlk_js_music_play,      DUK_VARARGS     },
 	{ NULL,         NULL,                   0               }
 };
 
-static const duk_function_list_entry methods[] = {
-	{ "play",       mlk_js_music_play,      DUK_VARARGS     },
+static const duk_function_list_entry functions[] = {
+	{ "fromFile",   mlk_js_music_fromFile,  1               },
+	{ "fromVFS",    mlk_js_music_fromVFS,   1               },
 	{ NULL,         NULL,                   0               }
 };
 
@@ -143,14 +163,33 @@
 
 	duk_push_global_object(ctx);
 	duk_get_prop_string(ctx, -1, "Mlk");
-	duk_push_c_function(ctx, mlk_js_music_new, 3);
+	duk_push_object(ctx);
 	duk_put_function_list(ctx, -1, functions);
 	duk_put_number_list(ctx, -1, flags);
 	duk_push_object(ctx);
 	duk_put_function_list(ctx, -1, methods);
 	duk_push_c_function(ctx, mlk_js_music_finish, 1);
 	duk_set_finalizer(ctx, -2);
+	duk_push_global_stash(ctx);
+	duk_dup(ctx, -2);
+	duk_put_prop_string(ctx, -2, PROTO);
+	duk_pop(ctx);
 	duk_put_prop_string(ctx, -2, "prototype");
 	duk_put_prop_string(ctx, -2, "Music");
 	duk_pop_n(ctx, 2);
 }
+
+void
+mlk_js_music_push(duk_context *ctx, const struct mlk_music *mus)
+{
+	assert(ctx);
+	assert(mus);
+
+	duk_push_object(ctx);
+	duk_push_global_stash(ctx);
+	duk_get_prop_string(ctx, -1, PROTO);
+	duk_remove(ctx, -2);
+	duk_push_pointer(ctx, mlk_alloc_dup(mus, 1, sizeof (*mus)));
+	duk_put_prop_string(ctx, -3, SYMBOL);
+	duk_set_prototype(ctx, -2);
+}
--- a/libmlk-core/mlk/core/js/js-music.h	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-music.h	Sat Dec 23 09:34:04 2023 +0100
@@ -21,6 +21,8 @@
 
 #include <duktape.h>
 
+struct mlk_music;
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -28,6 +30,9 @@
 void
 mlk_js_music_load(duk_context *ctx);
 
+void
+mlk_js_music_push(duk_context *ctx, const struct mlk_music *mus);
+
 #if defined(__cplusplus)
 }
 #endif
--- a/libmlk-core/mlk/core/js/js-sound.c	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-sound.c	Sat Dec 23 09:34:04 2023 +0100
@@ -21,10 +21,13 @@
 #include <mlk/core/alloc.h>
 #include <mlk/core/err.h>
 #include <mlk/core/sound.h>
+#include <mlk/core/vfs.h>
 
 #include "js-sound.h"
+#include "js.h"
 
 #define SYMBOL DUK_HIDDEN_SYMBOL("mlk::sound")
+#define PROTO  DUK_HIDDEN_SYMBOL("mlk::sound::proto")
 
 static struct mlk_sound *
 mlk_js_sound_this(duk_context *ctx)
@@ -43,28 +46,6 @@
 }
 
 static duk_ret_t
-mlk_js_sound_new(duk_context *ctx)
-{
-	struct mlk_sound snd;
-	const char *path;
-
-	if (!duk_is_constructor_call(ctx))
-		return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Sound must be new-constructed");
-
-	path = duk_require_string(ctx, 0);
-
-	if (mlk_sound_open(&snd, path) < 0)
-		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
-
-	duk_push_this(ctx);
-	duk_push_pointer(ctx, mlk_alloc_dup(&snd, 1, sizeof (snd)));
-	duk_put_prop_string(ctx, -2, SYMBOL);
-	duk_pop(ctx);
-
-	return 0;
-}
-
-static duk_ret_t
 mlk_js_sound_play(duk_context *ctx)
 {
 	struct mlk_sound *snd = mlk_js_sound_this(ctx);
@@ -117,12 +98,55 @@
 	return 0;
 }
 
+static duk_ret_t
+mlk_js_sound_fromFile(duk_context *ctx)
+{
+	const char *path = duk_require_string(ctx, 0);
+	struct mlk_sound snd;
+
+	if (mlk_sound_open(&snd, path) < 0)
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	mlk_js_sound_push(ctx, &snd);
+
+	return 1;
+}
+
+static duk_ret_t
+mlk_js_sound_fromVFS(duk_context *ctx)
+{
+	const char *path = duk_require_string(ctx, 0);
+	struct mlk_vfs *vfs = mlk_js_require(ctx)->vfs;
+	struct mlk_vfs_file *file;
+	struct mlk_sound snd;
+	int rv;
+
+	if (!(file = mlk_vfs_open(vfs, path, "r")))
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	rv = mlk_sound_openvfs(&snd, file);
+	mlk_vfs_file_finish(file);
+
+	if (rv < 0)
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	mlk_js_sound_push(ctx, &snd);
+
+	return 1;
+}
+
 static const duk_function_list_entry methods[] = {
-	{ "play",               mlk_js_sound_play,      DUK_VARARGS     },
-	{ "pause",              mlk_js_sound_pause,     0               },
-	{ "resume",             mlk_js_sound_resume,    0               },
-	{ "stop",               mlk_js_sound_stop,      DUK_VARARGS     },
-	{ NULL,                 NULL,                   0               }
+	{ "play",       mlk_js_sound_play,      DUK_VARARGS     },
+	{ "pause",      mlk_js_sound_pause,     0               },
+	{ "resume",     mlk_js_sound_resume,    0               },
+	{ "stop",       mlk_js_sound_stop,      DUK_VARARGS     },
+	{ NULL,         NULL,                   0               }
+};
+
+static const duk_function_list_entry functions[] = {
+	{ "fromFile",   mlk_js_sound_fromFile,  1               },
+	{ "fromVFS",    mlk_js_sound_fromVFS,   1               },
+	{ NULL,         NULL,                   0               }
 };
 
 void
@@ -132,12 +156,32 @@
 
 	duk_push_global_object(ctx);
 	duk_get_prop_string(ctx, -1, "Mlk");
-	duk_push_c_function(ctx, mlk_js_sound_new, 3);
+	duk_push_object(ctx);
+	duk_put_function_list(ctx, -1, functions);
 	duk_push_object(ctx);
 	duk_put_function_list(ctx, -1, methods);
 	duk_push_c_function(ctx, mlk_js_sound_finish, 1);
 	duk_set_finalizer(ctx, -2);
+	duk_push_global_stash(ctx);
+	duk_dup(ctx, -2);
+	duk_put_prop_string(ctx, -2, PROTO);
+	duk_pop(ctx);
 	duk_put_prop_string(ctx, -2, "prototype");
 	duk_put_prop_string(ctx, -2, "Sound");
 	duk_pop_n(ctx, 2);
 }
+
+void
+mlk_js_sound_push(duk_context *ctx, const struct mlk_sound *snd)
+{
+	assert(ctx);
+	assert(snd);
+
+	duk_push_object(ctx);
+	duk_push_global_stash(ctx);
+	duk_get_prop_string(ctx, -1, PROTO);
+	duk_remove(ctx, -2);
+	duk_push_pointer(ctx, mlk_alloc_dup(snd, 1, sizeof (*snd)));
+	duk_put_prop_string(ctx, -3, SYMBOL);
+	duk_set_prototype(ctx, -2);
+}
--- a/libmlk-core/mlk/core/js/js-sound.h	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-sound.h	Sat Dec 23 09:34:04 2023 +0100
@@ -21,6 +21,8 @@
 
 #include <duktape.h>
 
+struct mlk_sound;
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -28,6 +30,9 @@
 void
 mlk_js_sound_load(duk_context *ctx);
 
+void
+mlk_js_sound_push(duk_context *ctx, const struct mlk_sound *mus);
+
 #if defined(__cplusplus)
 }
 #endif
--- a/libmlk-core/mlk/core/js/js-texture.c	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-texture.c	Sat Dec 23 09:34:04 2023 +0100
@@ -22,6 +22,7 @@
 #include <mlk/core/err.h>
 #include <mlk/core/image.h>
 #include <mlk/core/texture.h>
+#include <mlk/core/vfs.h>
 
 #include "js-texture.h"
 #include "js.h"
@@ -173,7 +174,7 @@
 	duk_pop_n(ctx, 4);
 
 	/* Angle. */
-	angle = duk_to_number(ctx, 2);
+	angle = duk_is_number(ctx, 2) ? duk_to_number(ctx, 2) : 0;
 
 	if (mlk_texture_scale(tex, srcx, srcy, srcw, srch, dstx, dsty, dstw, dsth, angle) < 0)
 		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
@@ -213,6 +214,29 @@
 	return 1;
 }
 
+static duk_ret_t
+mlk_js_texture_fromVFS(duk_context *ctx)
+{
+	const char *path = duk_require_string(ctx, 0);
+	struct mlk_vfs *vfs = mlk_js_require(ctx)->vfs;
+	struct mlk_vfs_file *file;
+	struct mlk_texture tex;
+	int rv;
+
+	if (!(file = mlk_vfs_open(vfs, path, "r")))
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	rv = mlk_image_openvfs(&tex, file);
+	mlk_vfs_file_finish(file);
+
+	if (rv < 0)
+		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	mlk_js_texture_push(ctx, &tex);
+
+	return 1;
+}
+
 static const duk_function_list_entry methods[] = {
 	{ "draw",       mlk_js_texture_draw,            1 },
 	{ "scale",      mlk_js_texture_scale,           3 },
@@ -221,6 +245,7 @@
 
 static const duk_function_list_entry functions[] = {
 	{ "fromImage",  mlk_js_texture_fromImage,       1 },
+	{ "fromVFS",    mlk_js_texture_fromVFS,         1 },
 	{ NULL,         NULL,                           0 }
 };
 
--- a/libmlk-core/mlk/core/js/js.c	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js.c	Sat Dec 23 09:34:04 2023 +0100
@@ -25,7 +25,6 @@
 #include <mlk/core/trace.h>
 #include <mlk/core/vfs.h>
 
-#include <duktape.h>
 #include <duk_module.h>
 
 #include "js-animation.h"
@@ -100,22 +99,6 @@
 	return text;
 }
 
-static struct mlk_js *
-mlk_js_this(duk_context *ctx)
-{
-	struct mlk_js *js;
-
-	duk_push_global_stash(ctx);
-	duk_get_prop_string(ctx, -1, JS_REF);
-	js = duk_to_pointer(ctx, -1);
-	duk_pop(ctx);
-
-	if (!js)
-		duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Javascript context");
-
-	return js;
-}
-
 static duk_ret_t
 mlk_js_print(duk_context *ctx)
 {
@@ -140,7 +123,7 @@
 	char *text;
 	size_t textsz;
 
-	js = mlk_js_this(ctx);
+	js = mlk_js_require(ctx);
 	filename = duk_require_string(ctx, 0);
 
 	if (!(text = read_all(js, filename, &textsz)))
@@ -227,6 +210,24 @@
 	return 0;
 }
 
+struct mlk_js *
+mlk_js_require(duk_context *ctx)
+{
+	assert(ctx);
+
+	struct mlk_js *js;
+
+	duk_push_global_stash(ctx);
+	duk_get_prop_string(ctx, -1, JS_REF);
+	js = duk_to_pointer(ctx, -1);
+	duk_pop(ctx);
+
+	if (!js)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Javascript context");
+
+	return js;
+}
+
 int
 mlk_js_run(struct mlk_js *js, const char *main)
 {
--- a/libmlk-core/mlk/core/js/js.h	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/js/js.h	Sat Dec 23 09:34:04 2023 +0100
@@ -21,14 +21,22 @@
 
 #define MLK_CORE_JS_MAIN "main.js"
 
+#include <duktape.h>
+
 struct mlk_js {
 	/**
-	 * (read-write, borrowed)
+	 * (read-write)
 	 *
 	 * VFS used to load resources.
 	 */
 	struct mlk_vfs *vfs;
-	void *handle;
+
+	/**
+	 * (read-write)
+	 *
+	 * Duktape context.
+	 */
+	duk_context *handle;
 };
 
 struct mlk_vfs;
@@ -40,6 +48,9 @@
 int
 mlk_js_init(struct mlk_js *js, struct mlk_vfs *vfs);
 
+struct mlk_js *
+mlk_js_require(duk_context *ctx);
+
 int
 mlk_js_run(struct mlk_js *js, const char *main);
 
--- a/libmlk-core/mlk/core/vfs.c	Sun Dec 17 11:27:54 2023 +0100
+++ b/libmlk-core/mlk/core/vfs.c	Sat Dec 23 09:34:04 2023 +0100
@@ -121,8 +121,8 @@
 static int
 rw_vfs_file_close(SDL_RWops *context)
 {
-	free(context->hidden.mem.base);
-	free(context);
+	mlk_alloc_free(context->hidden.mem.base);
+	SDL_DestroyRW(context);
 
 	return 0;
 }
@@ -137,7 +137,7 @@
 	if (!(data = mlk_vfs_file_read_all(file, &datasz)))
 		return NULL;
 	if (!(ops = SDL_RWFromConstMem(data, datasz))) {
-		free(data);
+		mlk_alloc_free(data);
 		return mlk_errf("%s", SDL_GetError()), NULL;
 	}