diff --git a/Makefile b/Makefile index 3727afb..68d36f6 100644 --- a/Makefile +++ b/Makefile @@ -2,31 +2,46 @@ PROJECT = lua_libpulse_glib PREFIX ?= /usr/local BUILD_DIR = out -LUA_VERSION ?= 5.3 +LUA_VERSION ?= 5.1 LUA ?= $(shell command -v lua$(LUA_VERSION)) LUA_BINDIR ?= /usr/bin -# LUA_LIBDIR ?= /usr/lib +LUA_LIBDIR ?= /usr/lib/x86_64-linux-gnu/lua/$(LUA_VERSION) LUA_INCDIR ?= /usr/include/lua$(LUA_VERSION) -INSTALL_BINDIR ?= $(PREFIX)/bin +ifdef LIBDIR +INSTALL_LIBDIR ?= $(LIBDIR) +else INSTALL_LIBDIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) +endif + +ifdef LUADIR +INSTALL_LUADIR ?= $(LUADIR) +else INSTALL_LUADIR ?= $(PREFIX)/share/lua/$(LUA_VERSION) -INSTALL_CONFDIR ?= $(PREFIX)/etc +endif + +ifdef DOCDIR +INSTALL_DOCDIR ?= $(DOCDIR) +else +INSTALL_DOCDIR ?= $(PREFIX)/share/doc/$(PROJECT) +endif CC = gcc PKG_CONFIG ?= $(shell command -v pkg-config) -PKGS = glib-2.0 gobject-2.0 lua$(LUA_VERSION) +PKGS = libpulse-mainloop-glib glib-2.0 gobject-2.0 gobject-introspection-1.0 lua$(LUA_VERSION) CFLAGS ?= -fPIC LIBFLAG ?= -shared CCFLAGS ?= $(CFLAGS) -CCFLAGS += -Wall -g $(shell $(PKG_CONFIG) --cflags $(PKGS)) -I$(LUA_INCDIR) +CCFLAGS += -Wall -g -rdynamic $(shell $(PKG_CONFIG) --cflags $(PKGS)) -I$(LUA_INCDIR) -I"./" -LIBS = -L"$(LUA_LIBDIR)" -L$(shell dirname "$(shell $(CC) -print-libgcc-file-name)") +LIBS = -L$(shell dirname "$(shell $(CC) -print-libgcc-file-name)") -L"$(LUA_LIBDIR)" -L"./" LIBS += $(shell $(PKG_CONFIG) --libs $(PKGS)) -OBJS = $(shell find src -type f -iname '*.c' | sed 's/\(.*\)\.c$$/$(BUILD_DIR)\/\1\.so/') +OBJS = $(shell find src -type f -iname '*.c' | sed 's/\(.*\)\.c$$/$(BUILD_DIR)\/\1\.o/') + +TARGET = $(BUILD_DIR)/$(PROJECT).so ifdef CI CHECK_ARGS ?= --formatter TAP @@ -37,14 +52,14 @@ endif .PHONY: clean doc doc-content doc-styles install test check rock -build: $(OBJS) +build: $(TARGET) $(BUILD_DIR)/%.o: %.c @mkdir -p $(shell dirname "$@") $(CC) -c $(CCFLAGS) $< -o $@ -%.so: %.o - $(CC) $(LIBFLAG) -o $@ $< $(LIBS) +$(TARGET): $(OBJS) + $(CC) $(LIBFLAG) -o $@ $(OBJS) $(LIBS) doc-styles: @printf "\e[1;97mGenerate stylesheet\e[0m\n" @@ -66,18 +81,15 @@ clean: rm -r out/ install: build doc - @printf "\e[1;97mInstall C libraries\e[0m\n" - find $(BUILD_DIR)/src -type f -iname '*.so' | xargs install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) - - @printf "\e[1;97mInstall Lua libraries\e[0m\n" - find src/ -type f -iname '*.lua' | xargs install -vDm 644 -t $(INSTALL_LUADIR)/$(PROJECT) + @printf "\e[1;97mInstall C library\e[0m\n" + xargs install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) $(TARGET) @printf "\e[1;97mInstall documentation\e[0m\n" - install -vd $(PREFIX)/share/doc/$(PROJECT) - cp -vr $(BUILD_DIR)/doc/* $(PREFIX)/share/doc/$(PROJECT) + install -vd $(INSTALL_DOCDIR) + cp -vr $(BUILD_DIR)/doc/* $(INSTALL_DOCDIR) check: - find src/ -iname '*.lua' | xargs luacheck $(CHECK_ARGS) + @echo "Nothing to do" test: busted --config-file=.busted.lua --lua=$(LUA) $(TEST_ARGS) diff --git a/rocks/lua-libpulse-glib-scm-1.rockspec b/rocks/lua-libpulse-glib-scm-1.rockspec index c7cb947..5392e06 100644 --- a/rocks/lua-libpulse-glib-scm-1.rockspec +++ b/rocks/lua-libpulse-glib-scm-1.rockspec @@ -33,6 +33,7 @@ build = { INSTALL_LIBDIR="$(LIBDIR)", INSTALL_LUADIR="$(LUADIR)", INSTALL_CONFDIR="$(CONFDIR)", + INSTALL_DOCDIR="$(DOCDIR)", }, copy_directories = { "spec" diff --git a/src/lua_libpulse_glib/pulseaudio.c b/src/lua_libpulse_glib/pulseaudio.c new file mode 100644 index 0000000..fb86808 --- /dev/null +++ b/src/lua_libpulse_glib/pulseaudio.c @@ -0,0 +1,93 @@ +/// libpulse bindings. +// +// @module pulseaudio + +#include +#include +#include +#include + +#define LUA_MOD_EXPORT extern +#define LUA_PULSEAUDIO "pulseaudio" + + +#if LUA_VERSION_NUM <= 501 +// Shamelessly copied from Lua 5.3 source. +// TODO: Is there any official way to do this in 5.1? +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + if (l->func == NULL) /* place holder? */ + lua_pushboolean(L, 0); + else { + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + } + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +#define luaL_newlib(L,l) (luaL_register(L,LUA_PULSEAUDIO,l)) +#endif + + +typedef struct pulseaudio { + pa_glib_mainloop* mainloop; +} pulseaudio; + + +/** + * Creates a new PulseAudio object. + * + * The API requires a GLib Main Context internally. Currently, only the default context + * is supported. + * + * @return[type=PulseAudio] + */ +static int +pulseaudio_new(lua_State* L) +{ + GMainContext* ctx = g_main_context_default(); + if (ctx == NULL) { + lua_pushfstring(L, "Failed to accquire default GLib Main Context. Are we running in a Main Loop?"); + lua_error(L); + return 0; + } + + pulseaudio* pa = lua_newuserdata (L, sizeof(pulseaudio)); + if (!pa) { + return luaL_error(L, "failed to create pulseaudio userdata"); + } + luaL_getmetatable(L, LUA_PULSEAUDIO); + lua_setmetatable(L, -2); + + pa->mainloop = pa_glib_mainloop_new(ctx); + + return 1; +} + + +// TODO: Implement `__gc` meta method to free the inner `pa_glib_mainloop` +static const struct luaL_Reg pulseaudio_mt [] = { + {NULL, NULL} +}; + + +static const struct luaL_Reg pulseaudio_lib [] = { + {"new", pulseaudio_new}, + {NULL, NULL} +}; + + +LUA_MOD_EXPORT int luaopen_lua_libpulse_glib(lua_State* L) +{ + luaL_newmetatable(L, LUA_PULSEAUDIO); + luaL_setfuncs(L, pulseaudio_mt, 0); + + luaL_newlib(L, pulseaudio_lib); + return 1; +}