From 5562028792621f4ccf0d62eb612abc59ea62f305 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 6 Apr 2022 09:24:04 +0200 Subject: [PATCH 01/44] WIP --- .gdb_history | 190 ++++++++++++++ .gdbinit | 5 + Makefile | 6 + compile_commands.json | 90 +++++++ lua.debug | Bin 0 -> 923816 bytes src/lua_libpulse_glib/introspection.c | 354 +++++++++++++++++++++++--- test.lua | 46 ++++ 7 files changed, 662 insertions(+), 29 deletions(-) create mode 100644 .gdb_history create mode 100644 .gdbinit create mode 100644 compile_commands.json create mode 100755 lua.debug create mode 100644 test.lua diff --git a/.gdb_history b/.gdb_history new file mode 100644 index 0000000..922048e --- /dev/null +++ b/.gdb_history @@ -0,0 +1,190 @@ +b pulseaudio__index +b pulseaudio_new_context +r test.lua +r test.lua +b pulseaudio_new_context +b pulseaudio__index +r test.lua +c +c +info lua5.1 +help info +info program +info target +show debug-file-directory +r test.lua +r test.lua +help +help running +target exec +target exec ~/build/lua-5.1.5/src/lua +target exec /home/gerlui/build/lua-5.1.5/src/lua +help readelf +help +apropos symbol +symbol-file /home/gerlui/build/lua-5.1.5/src/lua +b pulseaudio__index +r test.lua +symbol-file /home/gerlui/build/lua-5.1.5/src/lua +b pulseaudio__index +r test.lua +b pulseaudio__index +b pulseaudio_new_context +r test.lua +source ~/.config/gdb/lua-gdb.py +dashboard +apropos arg +symbol-file lua.debug +help symbol-file +r +bpulseaudio_new_context +b pulseaudio_new_context +r +r +b pulseaudio__index +r +b pulseaudio_new_context +b pulseaudio__index +r test.lua +b lua_error +r +b longjmp +b lonjmp +luastack +dashboard +help show +apropos variable +info variables +info tvariables +info locals +info scope +info scope function +info line +info scope line +tui +tui enable +tui disable +dhasboard +dashboard +apropos arg +explore L +dashboard +luastack +luastack : +luastack L +luatraceback +luagetlocal +luagetlocal L +r +r +b pulseaudio__index +b pulseaudio_new_context +r +b lua_error +r +show directories +b pulseaudio__index +b pulseaudio_new_context +b lua_error +r +b pulseaudio_new_context +r +r test.lua +b pulseaudio_new_context +b pulseaudio__index +b lua_error +r +b pulseaudio__index +b pulseaudio_new_context +r +b pulseaudio_new_context +r +b pulseaudio_new_context +r test.lua +b pulseaudio_new_context +r +show directories +show directories +b pulseaudio_new_context +r +b pulseaudio_new_context +r +show directories +b pulseaudio_new_context +r +help +help running +dashboard +s +help running +s +help running +rs +b context_new +help c +c +r +n +n +b context_connect +r test.lua +s +s +s +q +b context_connect +run test.lua +symbol-file lua.debug +s +s +s +s +s +n +n +n +n +n +n +n +s +s +n +n +n +n +n +n +n +n +n +r test.lua +n +n +n +n +n +q +b context__gc +r test.lua +n +help running +dashboard +s +q +b context__gc +r +n +q +b context__gc +r +n +q +symbol-file lua.debug +b context_connect +r +b context_connect +r test.lua +b context_get_server_info +r +q diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..58e945c --- /dev/null +++ b/.gdbinit @@ -0,0 +1,5 @@ +symbol-file -readnow lua.debug +# source ~/.config/gdb/lua-gdb.py +set directories src/lua_libpulse_glib:/home/gerlui/build/lua-5.1.5/src +# set directories src/lua_libpulse_glib +set args test.lua diff --git a/Makefile b/Makefile index 68d36f6..0484ddf 100644 --- a/Makefile +++ b/Makefile @@ -96,3 +96,9 @@ test: rock: luarocks --local --lua-version $(LUA_VERSION) make rocks/lua-libpulse-glib-scm-1.rockspec + +run: build + env LUA_CPATH="./out/?.so;${LUA_CPATH}" $(LUA) test.lua + +debug: build + env LUA_CPATH="./out/?.so;${LUA_CPATH}" gdb $(LUA) diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..30a3490 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,90 @@ +[ + { + "arguments": [ + "/usr/bin/x86_64-linux-gnu-gcc-10", + "-c", + "-fPIC", + "-Wall", + "-g", + "-D_REENTRANT", + "-I/usr/include/gobject-introspection-1.0", + "-I/usr/include/glib-2.0", + "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include", + "-I/usr/include/lua5.1", + "-I/usr/include/lua5.1", + "-I./", + "src/lua_libpulse_glib/context.c", + "-o", + "out/src/lua_libpulse_glib/context.o" + ], + "directory": "/home/gerlui/projects/lgi-pulseaudio", + "file": "/home/gerlui/projects/lgi-pulseaudio/src/lua_libpulse_glib/context.c", + "output": "/home/gerlui/projects/lgi-pulseaudio/out/src/lua_libpulse_glib/context.o" + }, + { + "arguments": [ + "/usr/bin/x86_64-linux-gnu-gcc-10", + "-c", + "-fPIC", + "-Wall", + "-g", + "-D_REENTRANT", + "-I/usr/include/gobject-introspection-1.0", + "-I/usr/include/glib-2.0", + "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include", + "-I/usr/include/lua5.1", + "-I/usr/include/lua5.1", + "-I./", + "src/lua_libpulse_glib/pulseaudio.c", + "-o", + "out/src/lua_libpulse_glib/pulseaudio.o" + ], + "directory": "/home/gerlui/projects/lgi-pulseaudio", + "file": "/home/gerlui/projects/lgi-pulseaudio/src/lua_libpulse_glib/pulseaudio.c", + "output": "/home/gerlui/projects/lgi-pulseaudio/out/src/lua_libpulse_glib/pulseaudio.o" + }, + { + "arguments": [ + "/usr/bin/x86_64-linux-gnu-gcc-10", + "-c", + "-fPIC", + "-Wall", + "-g", + "-D_REENTRANT", + "-I/usr/include/gobject-introspection-1.0", + "-I/usr/include/glib-2.0", + "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include", + "-I/usr/include/lua5.1", + "-I/usr/include/lua5.1", + "-I./", + "src/lua_libpulse_glib/init.c", + "-o", + "out/src/lua_libpulse_glib/init.o" + ], + "directory": "/home/gerlui/projects/lgi-pulseaudio", + "file": "/home/gerlui/projects/lgi-pulseaudio/src/lua_libpulse_glib/init.c", + "output": "/home/gerlui/projects/lgi-pulseaudio/out/src/lua_libpulse_glib/init.o" + }, + { + "arguments": [ + "/usr/bin/x86_64-linux-gnu-gcc-10", + "-c", + "-fPIC", + "-Wall", + "-g", + "-D_REENTRANT", + "-I/usr/include/gobject-introspection-1.0", + "-I/usr/include/glib-2.0", + "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include", + "-I/usr/include/lua5.1", + "-I/usr/include/lua5.1", + "-I./", + "src/lua_libpulse_glib/introspection.c", + "-o", + "out/src/lua_libpulse_glib/introspection.o" + ], + "directory": "/home/gerlui/projects/lgi-pulseaudio", + "file": "/home/gerlui/projects/lgi-pulseaudio/src/lua_libpulse_glib/introspection.c", + "output": "/home/gerlui/projects/lgi-pulseaudio/out/src/lua_libpulse_glib/introspection.o" + } +] diff --git a/lua.debug b/lua.debug new file mode 100755 index 0000000000000000000000000000000000000000..e19e2479d0329b9f0a8d5761a53cf6436f285238 GIT binary patch literal 923816 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

6n7Z^8W_2 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%0Amk+5%~k#pJT_3DJ%L!j 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
bzhc+D^&U}VR;2o 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 %bv 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 ef7|TaH#2+xH;!NaoNZY9{3channels, 0); + int table_index = lua_gettop(L); + + for (int i = 0; i < spec->channels; ++i) { + lua_pushinteger(L, i+1); + lua_pushinteger(L, spec->map[i]); + lua_settable(L, table_index); + } +} + + +void +sample_spec_to_lua(lua_State* L, const pa_sample_spec* spec) +{ + lua_createtable(L, 0, 3); + int table_index = lua_gettop(L); + + lua_pushstring(L, "rate"); + lua_pushinteger(L, spec->rate); + lua_settable(L, table_index); + + lua_pushstring(L, "channels"); + lua_pushinteger(L, spec->channels); + lua_settable(L, table_index); + + lua_pushstring(L, "format"); + lua_pushinteger(L, spec->format); + lua_settable(L, table_index); +} + + +void +volume_to_lua(lua_State* L, const pa_cvolume* volume) +{ + lua_createtable(L, volume->channels, 0); + int table_index = lua_gettop(L); + + for (int i = 0; i < volume->channels; ++i) { + lua_pushinteger(L, i+1); + lua_pushinteger(L, volume->values[i]); + lua_settable(L, table_index); + } +} + + +void +sink_port_info_to_lua(lua_State* L, const pa_sink_port_info* info) +{ + lua_createtable(L, 0, 6); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "priority"); + lua_pushinteger(L, info->priority); + lua_settable(L, table_index); + + lua_pushstring(L, "available"); + lua_pushinteger(L, info->available); + lua_settable(L, table_index); + + lua_pushstring(L, "availability_group"); + lua_pushstring(L, info->availability_group); + lua_settable(L, table_index); + + lua_pushstring(L, "type"); + lua_pushinteger(L, info->type); + lua_settable(L, table_index); +} + + +void +format_info_to_lua(lua_State* L, const pa_format_info* info) +{ + lua_createtable(L, 0, 6); + int table_index = lua_gettop(L); + + lua_pushstring(L, "encoding"); + lua_pushinteger(L, info->encoding); + lua_settable(L, table_index); + + // TODO: + // lua_pushstring(L, "plist"); + // proplist_to_lua(L, &info->plist); + // lua_settable(L, table_index); +} + + +void +ports_to_lua(lua_State* L, const pa_sink_port_info** list, int n_ports, const pa_sink_port_info* active) +{ + lua_createtable(L, 1, n_ports); + int table_index = lua_gettop(L); + + for (int i = 0; i < n_ports; ++i) { + lua_pushinteger(L, i+1); + sink_port_info_to_lua(L, list[i]); + + if (list[i] == active) { + lua_pushstring(L, "active"); + lua_pushvalue(L, -2); + lua_settable(L, table_index); + } + + lua_settable(L, table_index); + } +} + + +void +formats_to_lua(lua_State* L, const pa_format_info** list, int n_formats) +{ + lua_createtable(L, 0, n_formats); + int table_index = lua_gettop(L); + + for (int i = 0; i < n_formats; ++i) { + lua_pushinteger(L, i+1); + format_info_to_lua(L, list[i]); + lua_settable(L, table_index); + } +} + + +void +sink_info_to_lua(lua_State* L, const pa_sink_info* info) +{ + lua_createtable(L, 0, 24); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "index"); + lua_pushinteger(L, info->index); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); + + lua_pushstring(L, "owner_module"); + lua_pushinteger(L, info->owner_module); + lua_settable(L, table_index); + + lua_pushstring(L, "volume"); + volume_to_lua(L, &info->volume); + lua_settable(L, table_index); + + lua_pushstring(L, "mute"); + lua_pushinteger(L, info->mute); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_source"); + lua_pushinteger(L, info->monitor_source); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_source_name"); + lua_pushstring(L, info->monitor_source_name); + lua_settable(L, table_index); + + lua_pushstring(L, "latency"); + lua_pushinteger(L, info->latency); + lua_settable(L, table_index); + + lua_pushstring(L, "driver"); + lua_pushstring(L, info->driver); + lua_settable(L, table_index); + + lua_pushstring(L, "flags"); + lua_pushinteger(L, info->flags); + lua_settable(L, table_index); + + // TODO: The proplist needs more advanced handling + // lua_pushstring(L, "proplist"); + // proplist_to_lua(L, &info->proplist); + // lua_settable(L, table_index); + + lua_pushstring(L, "base_volume"); + lua_pushinteger(L, info->base_volume); + lua_settable(L, table_index); + + lua_pushstring(L, "state"); + lua_pushinteger(L, info->state); + lua_settable(L, table_index); + + lua_pushstring(L, "n_volume_steps"); + lua_pushinteger(L, info->n_volume_steps); + lua_settable(L, table_index); + + lua_pushstring(L, "card"); + lua_pushinteger(L, info->card); + lua_settable(L, table_index); + + lua_pushstring(L, "ports"); + ports_to_lua(L, info->ports, info->n_ports, info->active_port); + lua_settable(L, table_index); + + lua_pushstring(L, "formats"); + formats_to_lua(L, info->formats, info->n_formats); + lua_settable(L, table_index); +} + + +void +source_info_to_lua(lua_State* L, const pa_source_info* info) +{ + lua_createtable(L, 0, 24); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "index"); + lua_pushinteger(L, info->index); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); + + lua_pushstring(L, "owner_module"); + lua_pushinteger(L, info->owner_module); + lua_settable(L, table_index); + + lua_pushstring(L, "volume"); + volume_to_lua(L, &info->volume); + lua_settable(L, table_index); + + lua_pushstring(L, "mute"); + lua_pushinteger(L, info->mute); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_of_sink"); + lua_pushinteger(L, info->monitor_of_sink); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_of_sink_name"); + lua_pushstring(L, info->monitor_of_sink_name); + lua_settable(L, table_index); + + lua_pushstring(L, "latency"); + lua_pushinteger(L, info->latency); + lua_settable(L, table_index); + + lua_pushstring(L, "driver"); + lua_pushstring(L, info->driver); + lua_settable(L, table_index); + + lua_pushstring(L, "flags"); + lua_pushinteger(L, info->flags); + lua_settable(L, table_index); + + // TODO: The proplist needs more advanced handling + // lua_pushstring(L, "proplist"); + // proplist_to_lua(L, &info->proplist); + // lua_settable(L, table_index); + + lua_pushstring(L, "configured_latency"); + lua_pushinteger(L, info->configured_latency); + lua_settable(L, table_index); + + lua_pushstring(L, "base_volume"); + lua_pushinteger(L, info->base_volume); + lua_settable(L, table_index); + + lua_pushstring(L, "state"); + lua_pushinteger(L, info->state); + lua_settable(L, table_index); + + lua_pushstring(L, "n_volume_steps"); + lua_pushinteger(L, info->n_volume_steps); + lua_settable(L, table_index); + + lua_pushstring(L, "card"); + lua_pushinteger(L, info->card); + lua_settable(L, table_index); + + lua_pushstring(L, "ports"); + ports_to_lua(L, info->ports, info->n_ports, info->active_port); + lua_settable(L, table_index); + + lua_pushstring(L, "formats"); + formats_to_lua(L, info->formats, info->n_formats); + lua_settable(L, table_index); +} + + void server_info_to_lua(lua_State* L, const pa_server_info* info) { @@ -40,11 +354,21 @@ server_info_to_lua(lua_State* L, const pa_server_info* info) lua_pushstring(L, info->default_sink_name); lua_settable(L, table_index); + lua_pushstring(L, "default_source_name"); + lua_pushstring(L, info->default_source_name); + lua_settable(L, table_index); + lua_pushstring(L, "cookie"); lua_pushinteger(L, info->cookie); lua_settable(L, table_index); - // TODO: Handle `sample_spec` and `channel_map` tables + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); } @@ -117,20 +441,6 @@ typedef struct sink_info_list_callback_data { } sink_info_list_callback_data; -void -sink_info_to_lua(lua_State* L, const pa_sink_info* info) -{ - lua_createtable(L, 0, 24); - int table_index = lua_gettop(L); - - lua_pushstring(L, "name"); - lua_pushstring(L, info->name); - lua_settable(L, table_index); - - // TODO: Handle rest of the table -} - - void sink_info_list_callback(pa_context* c, const pa_sink_info* info, int eol, void* userdata) { @@ -202,20 +512,6 @@ typedef struct source_info_list_callback_data { } source_info_list_callback_data; -void -source_info_to_lua(lua_State* L, const pa_source_info* info) -{ - lua_createtable(L, 0, 24); - int table_index = lua_gettop(L); - - lua_pushstring(L, "name"); - lua_pushstring(L, info->name); - lua_settable(L, table_index); - - // TODO: Handle rest of the table -} - - void source_info_list_callback(pa_context* c, const pa_source_info* info, int eol, void* userdata) { diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..2ec9c25 --- /dev/null +++ b/test.lua @@ -0,0 +1,46 @@ +local lgi = require("lgi") +local pulseaudio = require("lua_libpulse_glib") +local ppretty = require("pl.pretty") + +local loop = lgi.GLib.MainLoop.new() + +local pa = pulseaudio.new() +print("pulseaudio: ", pa) +local ctx = pa:context("test") +print("context: ", ctx) + +local function context_state_to_string(state) + return ({ + "unconnected", + "connecting", + "authorizing", + "setting_name", + "ready", + "failed", + "terminated" + })[state + 1] +end + +print("calling connect") +ctx:connect("localhost", function(_, state) + print("pulse connection: ", context_state_to_string(state)) + + if state == 4 then + ctx:get_server_info(function(_, info) + print("server info") + ppretty.dump(info) + end) + + ctx:get_sinks(function(_, list) + print("sinks") + ppretty.dump(list) + end) + + ctx:get_sources(function(_, list) + print("sources") + ppretty.dump(list) + end) + end +end) + +loop:run() From 26c093ec270cb4fc8ac8ff25426056f714edae91 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 20 Apr 2022 18:00:08 +0200 Subject: [PATCH 02/44] build: Fix color output in Makefile --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 68d36f6..9ce525b 100644 --- a/Makefile +++ b/Makefile @@ -62,14 +62,14 @@ $(TARGET): $(OBJS) $(CC) $(LIBFLAG) -o $@ $(OBJS) $(LIBS) doc-styles: - @printf "\e[1;97mGenerate stylesheet\e[0m\n" + @echo "\033[1;97mGenerate stylesheet\033[0m\n" sass doc/ldoc.scss $(BUILD_DIR)/doc/ldoc.css doc-content: @mkdir -p "$(BUILD_DIR)/doc" "$(BUILD_DIR)/src" - @printf "\e[1;97mPreprocess sources\e[0m\n" + @echo "\033[1;97mPreprocess sources\033[0m\n" sh tools/process_docs.sh "$(BUILD_DIR)" - @printf "\e[1;97mGenerate documentation\e[0m\n" + @echo "\033[1;97mGenerate documentation\033[0m\n" ldoc --config=doc/config.ld --dir "$(BUILD_DIR)/doc" --project $(PROJECT) "$(BUILD_DIR)/src" doc: doc-content doc-styles @@ -81,10 +81,10 @@ clean: rm -r out/ install: build doc - @printf "\e[1;97mInstall C library\e[0m\n" + @echo "\033[1;97mInstall C library\033[0m\n" xargs install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) $(TARGET) - @printf "\e[1;97mInstall documentation\e[0m\n" + @echo "\033[1;97mInstall documentation\033[0m\n" install -vd $(INSTALL_DOCDIR) cp -vr $(BUILD_DIR)/doc/* $(INSTALL_DOCDIR) From c47054e66ebe29179867c1accd3f79b4ca237481 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Thu, 21 Apr 2022 14:03:16 +0200 Subject: [PATCH 03/44] chore: Configure tooling --- .clang-format | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ .fdignore | 1 + .gitignore | 8 +++++- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 .clang-format create mode 100644 .fdignore diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..649fcb2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,75 @@ +--- +# kak: filetype=yaml +Language: Cpp +BasedOnStyle: LLVM +AlignArrayOfStructures: Left +AlignConsecutiveMacros: AcrossComments +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: AcrossComments +AlignConsecutiveDeclarations: None +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeInheritanceComma: false +BreakInheritanceList: AfterComma +ColumnLimit: 120 +Cpp11BracedListStyle: false +EmptyLineBeforeAccessModifier: Always +FixNamespaceComments: true +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(_test)?$' +IncludeIsMainSourceRegex: '' +IndentExternBlock: NoIndent +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 2 +# PackConstructorInitializers: CurrentLine +PointerAlignment: Left +ReferenceAlignment: Right +ReflowComments: true +# SeparateDefinitionBlocks: Leave +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +TabWidth: 4 diff --git a/.fdignore b/.fdignore new file mode 100644 index 0000000..89f9ac0 --- /dev/null +++ b/.fdignore @@ -0,0 +1 @@ +out/ diff --git a/.gitignore b/.gitignore index a06c9da..db23e87 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ out/ + +.gdb_history +.gdbinit +lua.debug + +.cache/clangd +compile_commands.json .sass-cache -.vscode/*.log From f8b2a45740e9e79dfc34350bef149afa4ee7e67d Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Fri, 22 Apr 2022 10:35:13 +0200 Subject: [PATCH 04/44] chore: Improve make recipe echoing Replaces GNU Make's default output, which simply dumps the whole whole command line, with a custom echo that skips most flags and uses bold text to distinguish it from command output. --- Makefile | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9ce525b..24f8559 100644 --- a/Makefile +++ b/Makefile @@ -56,20 +56,22 @@ build: $(TARGET) $(BUILD_DIR)/%.o: %.c @mkdir -p $(shell dirname "$@") - $(CC) -c $(CCFLAGS) $< -o $@ + @echo "\033[1;97m$(CC) $< -o $@\033[0m" + @$(CC) -c $(CCFLAGS) $< -o $@ $(TARGET): $(OBJS) - $(CC) $(LIBFLAG) -o $@ $(OBJS) $(LIBS) + @echo "\033[1;97m$(CC) -o $@\033[0m" + @$(CC) $(LIBFLAG) -o $@ $(OBJS) $(LIBS) doc-styles: - @echo "\033[1;97mGenerate stylesheet\033[0m\n" + @echo "\033[1;97mGenerate stylesheet\033[0m" sass doc/ldoc.scss $(BUILD_DIR)/doc/ldoc.css doc-content: @mkdir -p "$(BUILD_DIR)/doc" "$(BUILD_DIR)/src" - @echo "\033[1;97mPreprocess sources\033[0m\n" + @echo "\033[1;97mPreprocess sources\033[0m" sh tools/process_docs.sh "$(BUILD_DIR)" - @echo "\033[1;97mGenerate documentation\033[0m\n" + @echo "\033[1;97mGenerate documentation\033[0m" ldoc --config=doc/config.ld --dir "$(BUILD_DIR)/doc" --project $(PROJECT) "$(BUILD_DIR)/src" doc: doc-content doc-styles @@ -81,10 +83,10 @@ clean: rm -r out/ install: build doc - @echo "\033[1;97mInstall C library\033[0m\n" + @echo "\033[1;97mInstall C library\033[0m" xargs install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) $(TARGET) - @echo "\033[1;97mInstall documentation\033[0m\n" + @echo "\033[1;97mInstall documentation\033[0m" install -vd $(INSTALL_DOCDIR) cp -vr $(BUILD_DIR)/doc/* $(INSTALL_DOCDIR) From 366e08498ee54786cd5e76801f6c3ff486b99b28 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Fri, 22 Apr 2022 10:37:48 +0200 Subject: [PATCH 05/44] feat: Implement introspection for sinks and sources This provides a way to query the current state for the primary data structures, as well as common setters. --- doc/config.ld | 22 +- src/lua_libpulse_glib/callback.c | 51 + src/lua_libpulse_glib/callback.h | 42 + src/lua_libpulse_glib/context.c | 90 +- src/lua_libpulse_glib/context.h | 457 +++++++- src/lua_libpulse_glib/convert.c | 532 ++++++++++ src/lua_libpulse_glib/convert.h | 20 + src/lua_libpulse_glib/introspection.c | 1411 +++++++++++++++++++++---- src/lua_libpulse_glib/introspection.h | 10 - src/lua_libpulse_glib/lua_util.h | 15 + src/lua_libpulse_glib/proplist.c | 214 ++++ src/lua_libpulse_glib/proplist.h | 316 ++++++ src/lua_libpulse_glib/pulseaudio.c | 148 ++- src/lua_libpulse_glib/pulseaudio.h | 60 +- src/lua_libpulse_glib/volume.c | 307 ++++++ src/lua_libpulse_glib/volume.h | 237 +++++ tools/process_docs.sh | 2 +- 17 files changed, 3607 insertions(+), 327 deletions(-) create mode 100644 src/lua_libpulse_glib/callback.c create mode 100644 src/lua_libpulse_glib/callback.h create mode 100644 src/lua_libpulse_glib/convert.c create mode 100644 src/lua_libpulse_glib/convert.h delete mode 100644 src/lua_libpulse_glib/introspection.h create mode 100644 src/lua_libpulse_glib/lua_util.h create mode 100644 src/lua_libpulse_glib/proplist.c create mode 100644 src/lua_libpulse_glib/proplist.h create mode 100644 src/lua_libpulse_glib/volume.c create mode 100644 src/lua_libpulse_glib/volume.h diff --git a/doc/config.ld b/doc/config.ld index c990afc..f3babc2 100644 --- a/doc/config.ld +++ b/doc/config.ld @@ -1,13 +1,27 @@ -project = 'lgi-async-extra' -title = 'lgi-async-extra' -description = 'An asynchronous high(er)-level API wrapper for lua-lgi' +project = 'lua-libpulse-glib' +title = 'lua-libpulse-glib' +description = "Lua bindings for PulseAudio's libpulse, using the GLib Main Loop." + +full_description = [[ +While libpulse provides different event loop implementations, these bindings focus on the GLib comaptibility only. +Therefore, all asynchronous functions need to be executed inside a running GLib Main Loop. +For now, this loop has to run on GLib's default main context. Custom loop contexts are currently not supported. + +The majority of the API is callback-based asynchronous. Callbacks always receive any potential errors as their +first parameter, usually just the error message as string, or `nil` when there was no error. Additional parameters +may either be just a boolean, for operations that don't return data, or the actual queried data. + +All numeric indices (such as sink or source indices) are adjusted to be 1-based in typical Lua fashion. +This means that when comparing the output of calls like @{Context:get_sinks} to the output of tools like `pactl`, +indices will be off by one. +]] template = true format = 'discount' pretty = 'lua' -prettify_files = 'show' +-- prettify_files = 'show' backtick_references = false wrap = true no_space_before_args = true diff --git a/src/lua_libpulse_glib/callback.c b/src/lua_libpulse_glib/callback.c new file mode 100644 index 0000000..25eef27 --- /dev/null +++ b/src/lua_libpulse_glib/callback.c @@ -0,0 +1,51 @@ +#include "callback.h" + +#include "pulseaudio.h" + + +simple_callback_data* prepare_lua_callback(lua_State* L) { + // Prepare a new thread to run the callback with + lua_pushstring(L, LUA_PULSEAUDIO); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushstring(L, LUA_PA_REGISTRY); + lua_gettable(L, -2); + lua_State* thread = lua_newthread(L); + int thread_ref = luaL_ref(L, -2); + + // Copy the callback function to the thread's stack + lua_pushvalue(L, 2); + lua_xmove(L, thread, 1); + + simple_callback_data* data = malloc(sizeof(struct simple_callback_data)); + data->L = thread; + data->thread_ref = thread_ref; + data->is_list = false; + + return data; +} + + +void free_lua_callback(simple_callback_data* data) { + lua_State* L = data->L; + + // Remove thread reference + lua_pushstring(L, LUA_PULSEAUDIO); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushstring(L, LUA_PA_REGISTRY); + lua_gettable(L, -2); + luaL_unref(L, -1, data->thread_ref); + + free(data); +} + + +void success_callback(pa_context* c, int success, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; + lua_State* L = data->L; + + lua_pushnil(L); + lua_pushboolean(L, success); + lua_call(L, 2, 0); + + free_lua_callback(data); +} diff --git a/src/lua_libpulse_glib/callback.h b/src/lua_libpulse_glib/callback.h new file mode 100644 index 0000000..be9aa49 --- /dev/null +++ b/src/lua_libpulse_glib/callback.h @@ -0,0 +1,42 @@ +#ifndef callback_h_INCLUDED +#define callback_h_INCLUDED + + +#include +#include +#include + +typedef struct simple_callback_data { + lua_State* L; + int thread_ref; + // PulseAudio's introspection callbacks are used for operations that return single values, as well as operations + // that return a list. But the callback itself cannot know in which context it is called, so we have to provide + // that information explicitly. + bool is_list; +} simple_callback_data; + + +// Prepares a Lua thread that can call a Lua function as +// callback inside a PulseAudio callback. +// +// Assumes that the Lua function to call is at the top of the stack and copies it to the +// new thread. +// +// The thread will be kept in memory by a unique ref in the registry, so the callback has to +// `luaL_unref` that, to mark it for the garbage collector. +// +// The returned callback data needs to be `free()`d at the end of the callback. `free_lua_callback` +// handles both `free()` and `luaL_unref()`. +simple_callback_data* prepare_lua_callback(lua_State* L); + + +// Removes the thread reference, to allow the thread to be garbage collected, and `free`s +// the callback data. +void free_lua_callback(simple_callback_data* data); + + +// Simple implementation of `pa_context_success_cb_t` that calls a provided Lua function. +void success_callback(pa_context* c, int success, void* userdata); + +#endif // callback_h_INCLUDED + diff --git a/src/lua_libpulse_glib/context.c b/src/lua_libpulse_glib/context.c index 554237b..324a48f 100644 --- a/src/lua_libpulse_glib/context.c +++ b/src/lua_libpulse_glib/context.c @@ -1,12 +1,15 @@ - -#include "pulseaudio.h" #include "context.h" -#include "pulse/context.h" + +#include "callback.h" +#include "pulseaudio.h" + +#include +#include -void -context_state_callback(pa_context* c, void* userdata) -{ +/* Calls the user-provided callback with the updates state info. + */ +void context_state_callback(pa_context* c, void* userdata) { context_state_callback_data* data = (context_state_callback_data*) userdata; luaL_checktype(data->L, 1, LUA_TFUNCTION); luaL_checkudata(data->L, 2, LUA_PA_CONTEXT); @@ -23,9 +26,7 @@ context_state_callback(pa_context* c, void* userdata) } -int -context_new(lua_State* L, pa_mainloop_api* pa_api) -{ +int context_new(lua_State* L, pa_mainloop_api* pa_api) { const char* name = luaL_checkstring(L, -1); // TODO: libpulse recommends using `new_with_proplist` instead. But I need to figure out that `proplist` first. pa_context* ctx = pa_context_new(pa_api, name); @@ -33,7 +34,7 @@ context_new(lua_State* L, pa_mainloop_api* pa_api) return luaL_error(L, "failed to create pulseaudio context"); } - lua_pa_context* lgi_ctx = lua_newuserdata (L, sizeof(lua_pa_context)); + lua_pa_context* lgi_ctx = lua_newuserdata(L, sizeof(lua_pa_context)); if (lgi_ctx == NULL) { return luaL_error(L, "failed to create context userdata"); } @@ -48,19 +49,7 @@ context_new(lua_State* L, pa_mainloop_api* pa_api) } -int -context__index(lua_State* L) -{ - const char* index = luaL_checkstring(L, 2); - luaL_getmetatable(L, LUA_PA_CONTEXT); - lua_getfield(L, -1, index); - return 1; -} - - -int -context__gc(lua_State* L) -{ +int context__gc(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); if (ctx->connected == TRUE) { @@ -83,16 +72,14 @@ context__gc(lua_State* L) } -int -context_connect(lua_State* L) -{ +int context_connect(lua_State* L) { int nargs = lua_gettop(L); const char* server = NULL; if (lua_type(L, 2) == LUA_TSTRING) server = lua_tostring(L, 2); else if (lua_type(L, 2) != LUA_TNIL) { - const char *typearg; + const char* typearg; if (luaL_getmetafield(L, 2, "__name") == LUA_TSTRING) typearg = lua_tostring(L, -1); else if (lua_type(L, 2) == LUA_TLIGHTUSERDATA) @@ -141,11 +128,54 @@ context_connect(lua_State* L) } -int -context_get_state(lua_State* L) -{ +int context_disconnect(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + pa_context_disconnect(ctx->context); + return 0; +} + + +int context_get_state(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); pa_context_state_t state = pa_context_get_state(ctx->context); lua_pushinteger(L, state); return 1; } + + +int context_set_default_sink(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_set_default_sink(ctx->context, name, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set default sink: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_default_source(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_set_default_source(ctx->context, name, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set default source: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index 76870b8..a68c071 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -1,11 +1,20 @@ +/** Bindings for libpulse's connection context. + * + * The connection @{Context} provides introspection calls to query state from the server and various commands to + * change this state. + * + * In many cases, sinks and sources may be addressed by either their name or their numeric index. + * Both can be queried using the `get_(sink|source)_info` or `get_(sink|source)s` calls. + * + * @module pulseaudio.context + */ #pragma once -#include "stdbool.h" -#include "lua.h" -#include "lauxlib.h" -#include "pulse/context.h" -#include "pulse/mainloop-api.h" -#include "introspection.h" +#include +#include +#include +#include +#include #define LUA_PA_CONTEXT "pulseaudio.context" @@ -23,22 +32,428 @@ typedef struct lua_pa_context { } lua_pa_context; -int -context_new(lua_State*, pa_mainloop_api*); -int -context__index(lua_State*); -int -context__gc(lua_State*); -int -context_connect(lua_State*); +int context_new(lua_State*, pa_mainloop_api*); +int context__gc(lua_State*); -static const struct luaL_Reg context_mt [] = { - {"__index", context__index}, +/// Context +/// @type Context + + +/** Connects the context to the given server address. + * + * If the server address is `nil`, libpulse will attempt to connect to what it considers the default server. + * In most cases, this is the local machine. + * + * The provided callback function will be registered as state callback function, and will be called whenever the + * context's connection state changes. + * + * @function Context:connect + * @async + * @tparam[opt=nil] string server_address The server address. + * @tparam function cb The connection state callback. + * @treturn[opt] string The error message + * @treturn string The state + */ +int context_connect(lua_State*); + +/** Disconnects from the server. + * + * @function Context:disconnect + */ +int context_disconnect(lua_State* L); + + +/** Gets information about the server the context is connected to. + * + * See [pa_server_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__server__info.html) + * for documentation on the return type. + * + * This will fail when the connection state is anything other than `READY`. + * + * @function Context:get_server_info + * @async + * @tparam function cb + * @return[opt] string The error + * @return table The server info. + */ +int context_get_server_info(lua_State*); + + +// Sinks + + +/** Gets information about the given sink. + * + * The sink may be indicated by either its name or its index. + * + * See [pa_sink_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__sink__info.html) + * for documentation on the return type. + * + * @function Context:get_sink_info + * @async + * @tparam number|string sink The index or name of the sink to query. + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_sink_info(lua_State*); + +/** Gets information about all sinks. + * + * This returns the same information as @{Context:get_sink_info} would have returned for every sink + * that's currently registered at the server. + * + * See [pa_sink_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__sink__info.html) + * for documentation on the return type. + * + * @function Context:get_sinks + * @async + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_sink_info_list(lua_State*); +int context_get_sink_info_by_name(lua_State*); +int context_get_sink_info_by_index(lua_State*); + +/** Sets the sink's volume to the given value. + * + * The sink may be indicated by either its name or its index. + * + * @function Context:set_sink_volume + * @async + * @tparam number|string sink The sink to update. + * @tparam Volume volume + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_sink_volume(lua_State*); +int context_set_sink_volume_by_name(lua_State*); +int context_set_sink_volume_by_index(lua_State*); + +/** Sets the sink's mute state. + * + * The sink may be indicated by either its name or its index. + * + * @function Context:set_sink_mute + * @async + * @tparam number|string sink The sink to update. + * @tparam boolean mute + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_sink_mute(lua_State*); +int context_set_sink_mute_by_name(lua_State*); +int context_set_sink_mute_by_index(lua_State*); + +/** Sets the sink's suspended state. + * + * The sink may be indicated by either its name or its index. + * + * @function Context:set_sink_suspended + * @async + * @tparam number|string sink The sink to update. + * @tparam boolean suspended + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_sink_suspended(lua_State*); +int context_set_sink_suspended_by_name(lua_State*); +int context_set_sink_suspended_by_index(lua_State*); + + +// Sink Inputs + +/** Gets information about the given sink input. + * + * The sink input may be indicated by either its name or its index. + * + * See [pa_sink_input_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__sink_input__info.html) + * for documentation on the return type. + * + * @function Context:get_sink_input_info + * @async + * @tparam number|string sink input The index or name of the sink input to query. + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_sink_input_info(lua_State*); + +/** Gets information about all sink inputs. + * + * This returns the same information as @{Context:get_sink_input_info} would have returned for every sink input + * that's currently registered at the server. + * + * See [pa_sink_input_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__sink_input__info.html) + * for documentation on the return type. + * + * @function Context:get_sink_inputs + * @async + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_sink_input_info_list(lua_State*); + + +/** Moves the sink input to a different name. + * + * The target sink may be indicated by either its name or its index. + * + * @function Context:set_sink_suspended + * @async + * @tparam number The sink input to move. + * @tparam number|string sink The sink to update. + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_move_sink_input(lua_State*); +int context_move_sink_input_by_name(lua_State*); +int context_move_sink_input_by_index(lua_State*); + +/** Sets the sink input's volume to the given value. + * + * @function Context:set_sink_input_volume + * @async + * @tparam number sink_input The sink input to update. + * @tparam Volume volume + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_sink_input_volume(lua_State*); + +/** Sets the sink input's mute state. + * + * @function Context:set_sink_input_mute + * @async + * @tparam number sink_input The sink input to update. + * @tparam boolean mute + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_sink_input_mute(lua_State*); + +/** Kills the sink input. + * + * @function Context:kill_sink_input + * @async + * @tparam number sink_input The sink input to kill. + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_kill_sink_input(lua_State*); + + +// Sources + +/** Gets information about the given source. + * + * The source may be indicated by either its name or its index. + * + * See [pa_source_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__source__info.html) + * for documentation on the return type. + * + * @function Context:get_source_info + * @async + * @tparam number|string source The index or name of the source to query. + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_source_info(lua_State*); + +/** Gets information about all sources. + * + * This returns the same information as @{Context:get_source_info} would have returned for every source + * that's currently registered at the server. + * + * See [pa_source_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__source__info.html) + * for documentation on the return type. + * + * @function Context:get_sources + * @async + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_source_info_list(lua_State*); +int context_get_source_info_by_name(lua_State*); +int context_get_source_info_by_index(lua_State*); + +/** Sets the source's volume to the given value. + * + * The source may be indicated by either its name or its index. + * + * @function Context:set_source_volume + * @async + * @tparam number|string source The source to update. + * @tparam Volume volume + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_source_volume(lua_State*); +int context_set_source_volume_by_name(lua_State*); +int context_set_source_volume_by_index(lua_State*); + +/** Sets the source's mute state. + * + * The source may be indicated by either its name or its index. + * + * @function Context:set_source_mute + * @async + * @tparam number|string source The source to update. + * @tparam boolean mute + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_source_mute(lua_State*); +int context_set_source_mute_by_name(lua_State*); +int context_set_source_mute_by_index(lua_State*); + +/** Sets the source's suspended state. + * + * The source may be indicated by either its name or its index. + * + * @function Context:set_source_suspended + * @async + * @tparam number|string source The source to update. + * @tparam boolean suspended + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_source_suspended(lua_State*); +int context_set_source_suspended_by_name(lua_State*); +int context_set_source_suspended_by_index(lua_State*); + + +// Source Outputs + +/** Gets information about the given source output. + * + * See [pa_source_output_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__source_output__info.html) + * for documentation on the return type. + * + * @function Context:get_source_output_info + * @async + * @tparam number source_output The index of the source output to query. + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_source_output_info(lua_State*); + +/** Gets information about all source outputs. + * + * This returns the same information as @{Context:get_source_output_info} would have returned for every source output + * that's currently registered at the server. + * + * See [pa_source_output_info](https://freedesktop.org/software/pulseaudio/doxygen/structpa__source_output__info.html) + * for documentation on the return type. + * + * @function Context:get_source_outputs + * @async + * @tparam function cb + * @treturn[opt] string + * @treturn table + */ +int context_get_source_output_info_list(lua_State*); + +/** Moves the source output to a different name. + * + * The target source may be indicated by either its name or its index. + * + * @function Context:set_source_suspended + * @async + * @tparam number The source output to move. + * @tparam number|string source The source to update. + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_move_source_output(lua_State*); +int context_move_source_output_by_name(lua_State*); +int context_move_source_output_by_index(lua_State*); + + +/** Sets the source output's volume to the given value. + * + * @function Context:set_source_output_volume + * @async + * @tparam number source_output The source output to update. + * @tparam Volume volume + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_source_output_volume(lua_State*); + +/** Sets the source output's mute state. + * + * @function Context:set_source_output_mute + * @async + * @tparam number source_output The source output to update. + * @tparam boolean mute + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_set_source_output_mute(lua_State*); + +/** Kills the source output. + * + * @function Context:kill_source_output + * @async + * @tparam number source_output The source output to kill. + * @tparam function cb + * @treturn[opt] string + * @treturn boolean + */ +int context_kill_source_output(lua_State*); + + +static const struct luaL_Reg context_mt[] = { {"__gc", context__gc}, - {"connect", context_connect}, - {"get_server_info", context_get_server_info}, - {"get_sinks", context_get_sink_info_list}, - {"get_sources", context_get_source_info_list}, - {NULL, NULL} + { NULL, NULL } +}; + + +static const struct luaL_Reg context_f[] = { + {"connect", context_connect }, + { "disconnect", context_disconnect }, + { "get_server_info", context_get_server_info }, + { "get_sinks", context_get_sink_info_list }, + { "get_sink_info", context_get_sink_info }, + { "set_sink_volume", context_set_sink_volume }, + { "set_sink_mute", context_set_sink_mute }, + { "set_sink_suspended", context_set_sink_suspended }, + { "get_sink_inputs", context_get_sink_input_info_list }, + { "get_sink_input_info", context_get_sink_input_info }, + { "set_sink_input_volume", context_set_sink_input_volume }, + { "set_sink_input_mute", context_set_sink_input_mute }, + { "move_sink_input", context_move_sink_input }, + { "kill_sink_input", context_kill_sink_input }, + { "set_source_volume", context_set_source_volume }, + { "set_source_mute", context_set_source_mute }, + { "set_source_suspended", context_set_source_suspended }, + { "get_sources", context_get_source_info_list }, + { "get_source_info", context_get_source_info }, + { "get_source_outputs", context_get_source_output_info_list}, + { "get_source_output_info", context_get_source_output_info }, + { "set_source_output_volume", context_set_source_output_volume }, + { "set_source_output_mute", context_set_source_output_mute }, + { "move_source_output", context_move_source_output }, + { "kill_source_output", context_kill_source_output }, + { NULL, NULL } }; diff --git a/src/lua_libpulse_glib/convert.c b/src/lua_libpulse_glib/convert.c new file mode 100644 index 0000000..203ca81 --- /dev/null +++ b/src/lua_libpulse_glib/convert.c @@ -0,0 +1,532 @@ +#include "convert.h" + +#include "proplist.h" +#include "volume.h" + +#include + + +void channel_map_to_lua(lua_State* L, const pa_channel_map* spec) { + lua_createtable(L, spec->channels, 0); + int table_index = lua_gettop(L); + + for (int i = 0; i < spec->channels; ++i) { + lua_pushinteger(L, i + 1); + lua_pushinteger(L, spec->map[i]); + lua_settable(L, table_index); + } +} + + +void sample_spec_to_lua(lua_State* L, const pa_sample_spec* spec) { + lua_createtable(L, 0, 3); + int table_index = lua_gettop(L); + + lua_pushstring(L, "rate"); + lua_pushinteger(L, spec->rate); + lua_settable(L, table_index); + + lua_pushstring(L, "channels"); + lua_pushinteger(L, spec->channels); + lua_settable(L, table_index); + + lua_pushstring(L, "format"); + lua_pushinteger(L, spec->format); + lua_settable(L, table_index); +} + + +void sink_port_info_to_lua(lua_State* L, const pa_sink_port_info* info) { + lua_createtable(L, 0, 6); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "priority"); + lua_pushinteger(L, info->priority); + lua_settable(L, table_index); + + lua_pushstring(L, "available"); + lua_pushinteger(L, info->available); + lua_settable(L, table_index); + + lua_pushstring(L, "availability_group"); + lua_pushstring(L, info->availability_group); + lua_settable(L, table_index); + + lua_pushstring(L, "type"); + lua_pushinteger(L, info->type); + lua_settable(L, table_index); +} + + +void source_port_info_to_lua(lua_State* L, const pa_source_port_info* info) { + lua_createtable(L, 0, 6); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "priority"); + lua_pushinteger(L, info->priority); + lua_settable(L, table_index); + + lua_pushstring(L, "available"); + lua_pushinteger(L, info->available); + lua_settable(L, table_index); + + lua_pushstring(L, "availability_group"); + lua_pushstring(L, info->availability_group); + lua_settable(L, table_index); + + lua_pushstring(L, "type"); + lua_pushinteger(L, info->type); + lua_settable(L, table_index); +} + + +void format_info_to_lua(lua_State* L, const pa_format_info* info) { + lua_createtable(L, 0, 2); + int table_index = lua_gettop(L); + + lua_pushstring(L, "encoding"); + lua_pushinteger(L, info->encoding); + lua_settable(L, table_index); + + lua_pushstring(L, "plist"); + proplist_to_lua(L, pa_proplist_copy(info->plist)); + lua_settable(L, table_index); +} + + +void sink_ports_to_lua(lua_State* L, pa_sink_port_info** list, int n_ports, pa_sink_port_info* active) { + lua_createtable(L, n_ports, 1); + int table_index = lua_gettop(L); + + for (int i = 0; i < n_ports; ++i) { + lua_pushinteger(L, i + 1); + sink_port_info_to_lua(L, list[i]); + + if (list[i] == active) { + lua_pushstring(L, "active"); + lua_pushvalue(L, -2); + lua_settable(L, table_index); + } + + lua_settable(L, table_index); + } +} + + +void source_ports_to_lua(lua_State* L, pa_source_port_info** list, int n_ports, pa_source_port_info* active) { + lua_createtable(L, n_ports, 1); + int table_index = lua_gettop(L); + + for (int i = 0; i < n_ports; ++i) { + lua_pushinteger(L, i + 1); + source_port_info_to_lua(L, list[i]); + + if (list[i] == active) { + lua_pushstring(L, "active"); + lua_pushvalue(L, -2); + lua_settable(L, table_index); + } + + lua_settable(L, table_index); + } +} + + +void formats_to_lua(lua_State* L, pa_format_info** list, int n_formats) { + lua_createtable(L, n_formats, 0); + int table_index = lua_gettop(L); + + for (int i = 0; i < n_formats; ++i) { + lua_pushinteger(L, i + 1); + format_info_to_lua(L, list[i]); + lua_settable(L, table_index); + } +} + + +void sink_info_to_lua(lua_State* L, const pa_sink_info* info) { + lua_createtable(L, 0, 24); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "index"); + // Convert C's 0-based index to Lua's 1-base + lua_pushinteger(L, info->index + 1); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); + + lua_pushstring(L, "owner_module"); + lua_pushinteger(L, info->owner_module); + lua_settable(L, table_index); + + lua_pushstring(L, "volume"); + volume_to_lua(L, &info->volume); + lua_settable(L, table_index); + + lua_pushstring(L, "mute"); + lua_pushinteger(L, info->mute); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_source"); + lua_pushinteger(L, info->monitor_source); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_source_name"); + lua_pushstring(L, info->monitor_source_name); + lua_settable(L, table_index); + + lua_pushstring(L, "latency"); + lua_pushinteger(L, info->latency); + lua_settable(L, table_index); + + lua_pushstring(L, "driver"); + lua_pushstring(L, info->driver); + lua_settable(L, table_index); + + lua_pushstring(L, "flags"); + lua_pushinteger(L, info->flags); + lua_settable(L, table_index); + + lua_pushstring(L, "proplist"); + proplist_to_lua(L, pa_proplist_copy(info->proplist)); + lua_settable(L, table_index); + + lua_pushstring(L, "base_volume"); + lua_pushinteger(L, info->base_volume); + lua_settable(L, table_index); + + lua_pushstring(L, "state"); + lua_pushinteger(L, info->state); + lua_settable(L, table_index); + + lua_pushstring(L, "n_volume_steps"); + lua_pushinteger(L, info->n_volume_steps); + lua_settable(L, table_index); + + lua_pushstring(L, "card"); + lua_pushinteger(L, info->card); + lua_settable(L, table_index); + + lua_pushstring(L, "ports"); + sink_ports_to_lua(L, info->ports, info->n_ports, info->active_port); + lua_settable(L, table_index); + + lua_pushstring(L, "formats"); + formats_to_lua(L, info->formats, info->n_formats); + lua_settable(L, table_index); +} + + +void source_info_to_lua(lua_State* L, const pa_source_info* info) { + lua_createtable(L, 0, 24); + int table_index = lua_gettop(L); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "index"); + // Convert C's 0-based index to Lua's 1-base + lua_pushinteger(L, info->index + 1); + lua_settable(L, table_index); + + lua_pushstring(L, "description"); + lua_pushstring(L, info->description); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); + + lua_pushstring(L, "owner_module"); + lua_pushinteger(L, info->owner_module); + lua_settable(L, table_index); + + lua_pushstring(L, "volume"); + volume_to_lua(L, &info->volume); + lua_settable(L, table_index); + + lua_pushstring(L, "mute"); + lua_pushinteger(L, info->mute); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_of_sink"); + lua_pushinteger(L, info->monitor_of_sink); + lua_settable(L, table_index); + + lua_pushstring(L, "monitor_of_sink_name"); + lua_pushstring(L, info->monitor_of_sink_name); + lua_settable(L, table_index); + + lua_pushstring(L, "latency"); + lua_pushinteger(L, info->latency); + lua_settable(L, table_index); + + lua_pushstring(L, "driver"); + lua_pushstring(L, info->driver); + lua_settable(L, table_index); + + lua_pushstring(L, "flags"); + lua_pushinteger(L, info->flags); + lua_settable(L, table_index); + + lua_pushstring(L, "proplist"); + proplist_to_lua(L, pa_proplist_copy(info->proplist)); + lua_settable(L, table_index); + + lua_pushstring(L, "configured_latency"); + lua_pushinteger(L, info->configured_latency); + lua_settable(L, table_index); + + lua_pushstring(L, "base_volume"); + lua_pushinteger(L, info->base_volume); + lua_settable(L, table_index); + + lua_pushstring(L, "state"); + lua_pushinteger(L, info->state); + lua_settable(L, table_index); + + lua_pushstring(L, "n_volume_steps"); + lua_pushinteger(L, info->n_volume_steps); + lua_settable(L, table_index); + + lua_pushstring(L, "card"); + lua_pushinteger(L, info->card); + lua_settable(L, table_index); + + lua_pushstring(L, "ports"); + source_ports_to_lua(L, info->ports, info->n_ports, info->active_port); + lua_settable(L, table_index); + + lua_pushstring(L, "formats"); + formats_to_lua(L, info->formats, info->n_formats); + lua_settable(L, table_index); +} + + +void server_info_to_lua(lua_State* L, const pa_server_info* info) { + lua_createtable(L, 0, 9); + int table_index = lua_gettop(L); + + lua_pushstring(L, "user_name"); + lua_pushstring(L, info->user_name); + lua_settable(L, table_index); + + lua_pushstring(L, "host_name"); + lua_pushstring(L, info->host_name); + lua_settable(L, table_index); + + lua_pushstring(L, "server_version"); + lua_pushstring(L, info->server_version); + lua_settable(L, table_index); + + lua_pushstring(L, "server_name"); + lua_pushstring(L, info->server_name); + lua_settable(L, table_index); + + lua_pushstring(L, "default_sink_name"); + lua_pushstring(L, info->default_sink_name); + lua_settable(L, table_index); + + lua_pushstring(L, "default_source_name"); + lua_pushstring(L, info->default_source_name); + lua_settable(L, table_index); + + lua_pushstring(L, "cookie"); + lua_pushinteger(L, info->cookie); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); +} + + +void sink_input_info_to_lua(lua_State* L, const pa_sink_input_info* info) { + lua_createtable(L, 0, 15); + int table_index = lua_gettop(L); + + lua_pushstring(L, "index"); + lua_pushinteger(L, info->index + 1); + lua_settable(L, table_index); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "owner_module"); + lua_pushinteger(L, info->owner_module); + lua_settable(L, table_index); + + lua_pushstring(L, "client"); + lua_pushinteger(L, info->client); + lua_settable(L, table_index); + + lua_pushstring(L, "sink"); + lua_pushinteger(L, info->sink); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); + + lua_pushstring(L, "has_volume"); + lua_pushboolean(L, info->has_volume); + lua_settable(L, table_index); + + lua_pushstring(L, "volume_writable"); + lua_pushboolean(L, info->volume_writable); + lua_settable(L, table_index); + + if (info->has_volume) { + lua_pushstring(L, "volume"); + volume_to_lua(L, &info->volume); + lua_settable(L, table_index); + } + + lua_pushstring(L, "buffer_usec"); + lua_pushinteger(L, info->buffer_usec); + lua_settable(L, table_index); + + lua_pushstring(L, "sink_usec"); + lua_pushinteger(L, info->sink_usec); + lua_settable(L, table_index); + + lua_pushstring(L, "resample_method"); + lua_pushstring(L, info->resample_method); + lua_settable(L, table_index); + + lua_pushstring(L, "driver"); + lua_pushstring(L, info->driver); + lua_settable(L, table_index); + + lua_pushstring(L, "mute"); + lua_pushboolean(L, info->mute); + lua_settable(L, table_index); + + lua_pushstring(L, "format"); + format_info_to_lua(L, info->format); + lua_settable(L, table_index); + + lua_pushstring(L, "proplist"); + proplist_to_lua(L, pa_proplist_copy(info->proplist)); + lua_settable(L, table_index); +} + + +void source_output_info_to_lua(lua_State* L, const pa_source_output_info* info) { + lua_createtable(L, 0, 15); + int table_index = lua_gettop(L); + + lua_pushstring(L, "index"); + lua_pushinteger(L, info->index + 1); + lua_settable(L, table_index); + + lua_pushstring(L, "name"); + lua_pushstring(L, info->name); + lua_settable(L, table_index); + + lua_pushstring(L, "owner_module"); + lua_pushinteger(L, info->owner_module); + lua_settable(L, table_index); + + lua_pushstring(L, "client"); + lua_pushinteger(L, info->client); + lua_settable(L, table_index); + + lua_pushstring(L, "source"); + lua_pushinteger(L, info->source); + lua_settable(L, table_index); + + lua_pushstring(L, "sample_spec"); + sample_spec_to_lua(L, &info->sample_spec); + lua_settable(L, table_index); + + lua_pushstring(L, "channel_map"); + channel_map_to_lua(L, &info->channel_map); + lua_settable(L, table_index); + + lua_pushstring(L, "has_volume"); + lua_pushboolean(L, info->has_volume); + lua_settable(L, table_index); + + lua_pushstring(L, "volume_writable"); + lua_pushboolean(L, info->volume_writable); + lua_settable(L, table_index); + + if (info->has_volume) { + lua_pushstring(L, "volume"); + volume_to_lua(L, &info->volume); + lua_settable(L, table_index); + } + + lua_pushstring(L, "buffer_usec"); + lua_pushinteger(L, info->buffer_usec); + lua_settable(L, table_index); + + lua_pushstring(L, "source_usec"); + lua_pushinteger(L, info->source_usec); + lua_settable(L, table_index); + + lua_pushstring(L, "resample_method"); + lua_pushstring(L, info->resample_method); + lua_settable(L, table_index); + + lua_pushstring(L, "driver"); + lua_pushstring(L, info->driver); + lua_settable(L, table_index); + + lua_pushstring(L, "mute"); + lua_pushboolean(L, info->mute); + lua_settable(L, table_index); + + lua_pushstring(L, "format"); + format_info_to_lua(L, info->format); + lua_settable(L, table_index); + + lua_pushstring(L, "proplist"); + proplist_to_lua(L, pa_proplist_copy(info->proplist)); + lua_settable(L, table_index); +} diff --git a/src/lua_libpulse_glib/convert.h b/src/lua_libpulse_glib/convert.h new file mode 100644 index 0000000..f4ac1fa --- /dev/null +++ b/src/lua_libpulse_glib/convert.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + + +void channel_map_to_lua(lua_State*, const pa_channel_map*); +void sample_spec_to_lua(lua_State*, const pa_sample_spec*); +void sink_port_info_to_lua(lua_State*, const pa_sink_port_info*); +void source_port_info_to_lua(lua_State*, const pa_source_port_info*); +void format_info_to_lua(lua_State*, const pa_format_info*); +void sink_ports_to_lua(lua_State*, pa_sink_port_info**, int, pa_sink_port_info*); +void source_ports_to_lua(lua_State*, pa_source_port_info**, int, pa_source_port_info*); +void formats_to_lua(lua_State*, pa_format_info**, int); +void sink_info_to_lua(lua_State*, const pa_sink_info*); +void source_info_to_lua(lua_State*, const pa_source_info*); +void server_info_to_lua(lua_State*, const pa_server_info*); +void sink_input_info_to_lua(lua_State*, const pa_sink_input_info*); +void source_output_info_to_lua(lua_State*, const pa_source_output_info*); diff --git a/src/lua_libpulse_glib/introspection.c b/src/lua_libpulse_glib/introspection.c index b92dc13..3ac4b9e 100644 --- a/src/lua_libpulse_glib/introspection.c +++ b/src/lua_libpulse_glib/introspection.c @@ -1,78 +1,30 @@ -#include -#include -#include "introspection.h" +#include "callback.h" #include "context.h" +#include "convert.h" +#include "proplist.h" #include "pulseaudio.h" +#include "volume.h" + +#include +#include +#include +#include +#include -// TODO: Figure out error handling for callbacks - - -typedef struct server_info_callback_data { - lua_State* L; - int thread_ref; -} server_info_callback_data; - - -void -server_info_to_lua(lua_State* L, const pa_server_info* info) -{ - lua_createtable(L, 0, 9); - int table_index = lua_gettop(L); - - lua_pushstring(L, "user_name"); - lua_pushstring(L, info->user_name); - lua_settable(L, table_index); - - lua_pushstring(L, "host_name"); - lua_pushstring(L, info->host_name); - lua_settable(L, table_index); - - lua_pushstring(L, "server_version"); - lua_pushstring(L, info->server_version); - lua_settable(L, table_index); - - lua_pushstring(L, "server_name"); - lua_pushstring(L, info->server_name); - lua_settable(L, table_index); - - lua_pushstring(L, "default_sink_name"); - lua_pushstring(L, info->default_sink_name); - lua_settable(L, table_index); - - lua_pushstring(L, "cookie"); - lua_pushinteger(L, info->cookie); - lua_settable(L, table_index); - - // TODO: Handle `sample_spec` and `channel_map` tables -} - - -void -server_info_callback(pa_context* c, const pa_server_info* info, void* userdata) -{ - - server_info_callback_data* data = (server_info_callback_data*) userdata; +void server_info_callback(pa_context* c, const pa_server_info* info, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; lua_State* L = data->L; lua_pushnil(L); server_info_to_lua(L, info); lua_call(L, 2, 0); - // Remove thread reference - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - luaL_unref(L, -1, data->thread_ref); - - free(data); + free_lua_callback(data); } -int -context_get_server_info(lua_State* L) -{ +int context_get_server_info(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { @@ -82,21 +34,7 @@ context_get_server_info(lua_State* L) return 0; } - // Prepare a new thread to run the callback with - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - lua_State* thread = lua_newthread(L); - int thread_ref = luaL_ref(L, -2); - - // Copy the callback function to the thread's stack - lua_pushvalue(L, 2); - lua_xmove(L, thread, 1); - - server_info_callback_data* data = calloc(1, sizeof(struct server_info_callback_data)); - data->L = thread; - data->thread_ref = thread_ref; + simple_callback_data* data = prepare_lua_callback(L); pa_operation* op = pa_context_get_server_info(ctx->context, server_info_callback, data); if (op == NULL) { @@ -111,58 +49,42 @@ context_get_server_info(lua_State* L) } -typedef struct sink_info_list_callback_data { - lua_State* L; - int thread_ref; -} sink_info_list_callback_data; - - -void -sink_info_to_lua(lua_State* L, const pa_sink_info* info) -{ - lua_createtable(L, 0, 24); - int table_index = lua_gettop(L); - - lua_pushstring(L, "name"); - lua_pushstring(L, info->name); - lua_settable(L, table_index); - - // TODO: Handle rest of the table -} - - -void -sink_info_list_callback(pa_context* c, const pa_sink_info* info, int eol, void* userdata) -{ - sink_info_list_callback_data* data = (sink_info_list_callback_data*) userdata; +void sink_info_callback(pa_context* c, const pa_sink_info* info, int eol, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; lua_State* L = data->L; - if (eol == 0) { - int i = lua_objlen(L, 2); - lua_pushinteger(L, i+1); - sink_info_to_lua(L, info); - lua_settable(L, 2); + if (data->is_list) { + if (!eol) { + int i = lua_objlen(L, 2); + lua_pushinteger(L, i + 1); + sink_info_to_lua(L, info); + lua_settable(L, 2); + } else { + // Insert the error argument + lua_pushnil(L); + lua_insert(L, -2); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } } else { - // Insert the error argument - lua_pushnil(L); - lua_insert(L, -2); + if (!eol) { + lua_pushfstring(L, "only one sink info expected, but got multiple"); + lua_call(L, 1, 0); + } else { + lua_pushnil(L); + sink_info_to_lua(L, info); - lua_call(L, 2, 0); + lua_call(L, 2, 0); - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - luaL_unref(L, -1, data->thread_ref); - free(data); + free_lua_callback(data); + } } } -int -context_get_sink_info_list(lua_State* L) -{ +int context_get_sink_info_list(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { @@ -172,82 +94,96 @@ context_get_sink_info_list(lua_State* L) return 0; } - // Prepare a new thread to run the callback with - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - lua_State* thread = lua_newthread(L); - int thread_ref = luaL_ref(L, -2); + simple_callback_data* data = prepare_lua_callback(L); + data->is_list = true; + // Create the list to store infos in + lua_newtable(data->L); - // Copy the callback function to the thread's stack - lua_pushvalue(L, 2); - lua_xmove(L, thread, 1); + pa_operation* op = pa_context_get_sink_info_list(ctx->context, sink_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get sink info list: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } - // List to store the values in - lua_newtable(thread); - - sink_info_list_callback_data* data = calloc(1, sizeof(struct sink_info_list_callback_data)); - data->L = thread; - data->thread_ref = thread_ref; - - pa_context_get_sink_info_list(ctx->context, sink_info_list_callback, data); return 0; } -typedef struct source_info_list_callback_data { - lua_State* L; - int thread_ref; -} source_info_list_callback_data; +int context_get_sink_info_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } -void -source_info_to_lua(lua_State* L, const pa_source_info* info) -{ - lua_createtable(L, 0, 24); - int table_index = lua_gettop(L); + simple_callback_data* data = prepare_lua_callback(L); - lua_pushstring(L, "name"); - lua_pushstring(L, info->name); - lua_settable(L, table_index); + pa_operation* op = pa_context_get_sink_info_by_name(ctx->context, name, sink_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get sink info by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } - // TODO: Handle rest of the table + return 0; } -void -source_info_list_callback(pa_context* c, const pa_source_info* info, int eol, void* userdata) -{ - source_info_list_callback_data* data = (source_info_list_callback_data*) userdata; - lua_State* L = data->L; +int context_get_sink_info_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink index out of bounds. Got %d", index); + } - if (eol == 0) { - int i = lua_objlen(L, 2); - lua_pushinteger(L, i+1); - source_info_to_lua(L, info); - lua_settable(L, 2); - } else { - // Insert the error argument - lua_pushnil(L); - lua_insert(L, -2); + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } - lua_call(L, 2, 0); + simple_callback_data* data = prepare_lua_callback(L); - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); + pa_operation* op = pa_context_get_sink_info_by_index(ctx->context, (uint32_t) index - 1, sink_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get sink info by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - luaL_unref(L, -1, data->thread_ref); - free(data); + return 0; +} + + +int context_get_sink_info(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_get_sink_info_by_name(L); + } + case LUA_TNUMBER: { + return context_get_sink_info_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } } } -int -context_get_source_info_list(lua_State* L) -{ +int context_set_sink_volume_by_name(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { @@ -257,25 +193,1116 @@ context_get_source_info_list(lua_State* L) return 0; } - // Prepare a new thread to run the callback with - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - lua_State* thread = lua_newthread(L); - int thread_ref = luaL_ref(L, -2); + simple_callback_data* data = prepare_lua_callback(L); + const char* name = luaL_checkstring(L, 2); + pa_cvolume* volume = volume_from_lua(L, 3); - // Copy the callback function to the thread's stack - lua_pushvalue(L, 2); - lua_xmove(L, thread, 1); + pa_operation* op = pa_context_set_sink_volume_by_name(ctx->context, name, volume, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set sink volume by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + } - // List to store the values in - lua_newtable(thread); + // TODO: Is this too early? + // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. + // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. + pa_xfree((void*) volume); + + return 0; +} + + +int context_set_sink_volume_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink index out of bounds. Got %d", index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + pa_cvolume* volume = volume_from_lua(L, 3); + + pa_operation* op = + pa_context_set_sink_volume_by_index(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set sink volume by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + } + + // TODO: Is this too early? + // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. + // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. + pa_xfree((void*) volume); + + return 0; +} + + +int context_set_sink_volume(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_set_sink_volume_by_name(L); + } + case LUA_TNUMBER: { + return context_set_sink_volume_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_set_sink_mute_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + int mute = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_set_sink_mute_by_name(ctx->context, name, mute, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set sink mute by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_sink_mute_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink index out of bounds. Got %d", index); + } + int mute = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_set_sink_mute_by_index(ctx->context, (uint32_t) index - 1, mute, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set sink mute by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_sink_mute(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_set_sink_mute_by_name(L); + } + case LUA_TNUMBER: { + return context_set_sink_mute_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_set_sink_suspended_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + int suspended = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_suspend_sink_by_name(ctx->context, name, suspended, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set sink suspended by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_sink_suspended_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink index out of bounds. Got %d", index); + } + int suspended = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_suspend_sink_by_index(ctx->context, (uint32_t) index - 1, suspended, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set sink suspended by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_sink_suspended(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_set_sink_suspended_by_name(L); + } + case LUA_TNUMBER: { + return context_set_sink_suspended_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +// Can be used both functions that produce a single value or the `_list` versions. +// The `is_list` value on the userdata needs to be set accordingly. +// For lists, the callback will be called multiple times, once for each entry. +// The function that sets up the callback must make sure to push a table on the stack, where the +// values can be collected. +// +// @tparam pa_source_info* info Pointer to the data. +// @tparam boolean eol Indicates whether the last item of the list was reached. +// @tparam simple_callback_data* userdata Expected to be an instance of `simple_callback_data`. +void source_info_callback(pa_context* c, const pa_source_info* info, int eol, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; + lua_State* L = data->L; + + if (data->is_list) { + if (!eol) { + int i = lua_objlen(L, 2); + lua_pushinteger(L, i + 1); + source_info_to_lua(L, info); + lua_settable(L, 2); + } else { + // Insert the error argument + lua_pushnil(L); + lua_insert(L, -2); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } + } else { + if (!eol) { + lua_pushfstring(L, "only one source info expected, but got multiple"); + lua_call(L, 1, 0); + } else { + lua_pushnil(L); + source_info_to_lua(L, info); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } + } +} + + +int context_get_source_info_list(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + data->is_list = true; + // Create the list to store infos in + lua_newtable(data->L); + + pa_operation* op = pa_context_get_source_info_list(ctx->context, source_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get source info list: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_get_source_info_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_get_source_info_by_name(ctx->context, name, source_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get source info by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_get_source_info_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source index out of bounds. Got %d", index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_get_source_info_by_index(ctx->context, (uint32_t) index - 1, source_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get source info by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_get_source_info(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_get_source_info_by_name(L); + } + case LUA_TNUMBER: { + return context_get_source_info_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_set_source_volume_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + const char* name = luaL_checkstring(L, 2); + pa_cvolume* volume = volume_from_lua(L, 3); + + pa_operation* op = pa_context_set_source_volume_by_name(ctx->context, name, volume, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set source volume by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + } + + // TODO: Is this too early? + // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. + // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. + pa_xfree((void*) volume); + + return 0; +} + + +int context_set_source_volume_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source index out of bounds. Got %d", index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + pa_cvolume* volume = volume_from_lua(L, 3); + + pa_operation* op = + pa_context_set_source_volume_by_index(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set source volume by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + } + + // TODO: Is this too early? + // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. + // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. + pa_xfree((void*) volume); + + return 0; +} + + +int context_set_source_volume(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_set_source_volume_by_name(L); + } + case LUA_TNUMBER: { + return context_set_source_volume_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_set_source_mute_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + int mute = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_set_source_mute_by_name(ctx->context, name, mute, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set source mute by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_source_mute_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source index out of bounds. Got %d", index); + } + int mute = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_set_source_mute_by_index(ctx->context, (uint32_t) index - 1, mute, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set source mute by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_source_mute(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_set_source_mute_by_name(L); + } + case LUA_TNUMBER: { + return context_set_source_mute_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_set_source_suspended_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + const char* name = luaL_checkstring(L, 2); + int suspended = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_suspend_source_by_name(ctx->context, name, suspended, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set source suspended by name: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_source_suspended_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source index out of bounds. Got %d", index); + } + int suspended = lua_toboolean(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_suspend_source_by_index(ctx->context, (uint32_t) index - 1, suspended, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set source suspended by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_source_suspended(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_set_source_suspended_by_name(L); + } + case LUA_TNUMBER: { + return context_set_source_suspended_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +void sink_input_info_callback(pa_context* c, const pa_sink_input_info* info, int eol, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; + lua_State* L = data->L; + + if (data->is_list) { + if (!eol) { + int i = lua_objlen(L, 2); + lua_pushinteger(L, i + 1); + sink_input_info_to_lua(L, info); + lua_settable(L, 2); + } else { + // Insert the error argument + lua_pushnil(L); + lua_insert(L, -2); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } + } else { + if (!eol) { + lua_pushfstring(L, "only one sink input info expected, but got multiple"); + lua_call(L, 1, 0); + } else { + lua_pushnil(L); + sink_input_info_to_lua(L, info); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } + } +} + + +int context_get_sink_input_info_list(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + data->is_list = true; + // Create the list to store infos in + lua_newtable(data->L); + + pa_operation* op = pa_context_get_sink_input_info_list(ctx->context, sink_input_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get source info list: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_get_sink_input_info(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink input index out of bounds. Got %d", index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_get_sink_input_info(ctx->context, (uint32_t) index - 1, sink_input_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get sink input info by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_move_sink_input(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_move_sink_input_by_name(L); + } + case LUA_TNUMBER: { + return context_move_sink_input_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_move_sink_input_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer sink_input_index = luaL_checkinteger(L, 2); + if (sink_input_index < 1) { + return luaL_error(L, "Sink input index out of bounds. Got %d", sink_input_index); + } + + lua_Integer sink_index = luaL_checkinteger(L, 3); + if (sink_index < 1) { + return luaL_error(L, "Sink index out of bounds. Got %d", sink_index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_move_sink_input_by_index(ctx->context, + (uint32_t) sink_input_index - 1, + (uint32_t) sink_index - 1, + success_callback, + data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, + "failed to move sink input %d to sink %d: %s", + sink_input_index, + sink_index, + pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_move_sink_input_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer sink_input_index = luaL_checkinteger(L, 2); + if (sink_input_index < 1) { + return luaL_error(L, "Sink input index out of bounds. Got %d", sink_input_index); + } + + const char* sink_name = luaL_checkstring(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_move_sink_input_by_name(ctx->context, + (uint32_t) sink_input_index - 1, + sink_name, + success_callback, + data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, + "failed to move sink input %d to sink %s: %s", + sink_input_index, + sink_name, + pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_sink_input_volume(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink input index out of bounds. Got %d", index); + } + pa_cvolume* volume = volume_from_lua(L, 3); + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_set_sink_input_volume(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set volume for sink input %d: %s", index, pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_sink_input_mute(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink input index out of bounds. Got %d", index); + } + bool mute = lua_toboolean(L, 3); + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_set_sink_input_mute(ctx->context, (uint32_t) index - 1, mute, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set mute for sink input %d: %s", index, pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_kill_sink_input(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Sink input index out of bounds. Got %d", index); + } + + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_kill_sink_input(ctx->context, (uint32_t) index - 1, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to kill sink input %d: %s", index, pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +void source_output_info_callback(pa_context* c, const pa_source_output_info* info, int eol, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; + lua_State* L = data->L; + + if (data->is_list) { + if (!eol) { + int i = lua_objlen(L, 2); + lua_pushinteger(L, i + 1); + source_output_info_to_lua(L, info); + lua_settable(L, 2); + } else { + // Insert the error argument + lua_pushnil(L); + lua_insert(L, -2); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } + } else { + if (!eol) { + lua_pushfstring(L, "only one source output info expected, but got multiple"); + lua_call(L, 1, 0); + } else { + lua_pushnil(L); + source_output_info_to_lua(L, info); + + lua_call(L, 2, 0); + + free_lua_callback(data); + } + } +} + + +int context_get_source_output_info_list(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + data->is_list = true; + // Create the list to store infos in + lua_newtable(data->L); + + pa_operation* op = pa_context_get_source_output_info_list(ctx->context, source_output_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get source info list: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_get_source_output_info(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source output index out of bounds. Got %d", index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_get_source_output_info(ctx->context, (uint32_t) index - 1, source_output_info_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to get source output info by index: %s", pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_move_source_output(lua_State* L) { + switch (lua_type(L, 2)) { + case LUA_TSTRING: { + return context_move_source_output_by_name(L); + } + case LUA_TNUMBER: { + return context_move_source_output_by_index(L); + } + default: { + lua_pushfstring(L, "expected number or string, got %s", luaL_typename(L, 2)); + return luaL_argerror(L, 2, lua_tostring(L, -1)); + } + } +} + + +int context_move_source_output_by_index(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer source_output_index = luaL_checkinteger(L, 2); + if (source_output_index < 1) { + return luaL_error(L, "Source output index out of bounds. Got %d", source_output_index); + } + + lua_Integer source_index = luaL_checkinteger(L, 3); + if (source_index < 1) { + return luaL_error(L, "Source index out of bounds. Got %d", source_index); + } + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_move_source_output_by_index(ctx->context, + (uint32_t) source_output_index - 1, + (uint32_t) source_index - 1, + success_callback, + data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, + "failed to move source output %d to source %d: %s", + source_output_index, + source_index, + pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_move_source_output_by_name(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer source_output_index = luaL_checkinteger(L, 2); + if (source_output_index < 1) { + return luaL_error(L, "Source output index out of bounds. Got %d", source_output_index); + } + + const char* source_name = luaL_checkstring(L, 3); + + if (pa_context_get_state(ctx->context) != PA_CONTEXT_READY) { + lua_pushvalue(L, 2); + lua_pushstring(L, "connection not ready"); + lua_call(L, 1, 0); + return 0; + } + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_move_source_output_by_name(ctx->context, + (uint32_t) source_output_index - 1, + source_name, + success_callback, + data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, + "failed to move source output %d to source %s: %s", + source_output_index, + source_name, + pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_source_output_volume(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source output index out of bounds. Got %d", index); + } + pa_cvolume* volume = volume_from_lua(L, 3); + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_set_source_output_volume(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set volume for source output %d: %s", index, pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_set_source_output_mute(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source output index out of bounds. Got %d", index); + } + bool mute = lua_toboolean(L, 3); + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = + pa_context_set_source_output_mute(ctx->context, (uint32_t) index - 1, mute, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to set mute for source output %d: %s", index, pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } + + return 0; +} + + +int context_kill_source_output(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); + if (index < 1) { + return luaL_error(L, "Source output index out of bounds. Got %d", index); + } + + + simple_callback_data* data = prepare_lua_callback(L); + + pa_operation* op = pa_context_kill_source_output(ctx->context, (uint32_t) index - 1, success_callback, data); + if (op == NULL) { + int error = pa_context_errno(ctx->context); + lua_pushvalue(L, 2); + lua_pushfstring(L, "failed to kill source output %d: %s", index, pa_strerror(error)); + lua_call(L, 1, 0); + return 0; + } - source_info_list_callback_data* data = calloc(1, sizeof(struct source_info_list_callback_data)); - data->L = thread; - data->thread_ref = thread_ref; - - pa_context_get_source_info_list(ctx->context, source_info_list_callback, data); return 0; } diff --git a/src/lua_libpulse_glib/introspection.h b/src/lua_libpulse_glib/introspection.h deleted file mode 100644 index c998d16..0000000 --- a/src/lua_libpulse_glib/introspection.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "lua.h" - -int -context_get_server_info(lua_State*); -int -context_get_sink_info_list(lua_State*); -int -context_get_source_info_list(lua_State*); diff --git a/src/lua_libpulse_glib/lua_util.h b/src/lua_libpulse_glib/lua_util.h new file mode 100644 index 0000000..9f7a903 --- /dev/null +++ b/src/lua_libpulse_glib/lua_util.h @@ -0,0 +1,15 @@ +#ifndef lua_util_h_INCLUDED +#define lua_util_h_INCLUDED + +#include +#include + +#define LUA_MOD_EXPORT extern + + +typedef struct luaU_enumfield { + const char* name; + const char* value; +} luaU_enumfield; + +#endif // lua_util_h_INCLUDED diff --git a/src/lua_libpulse_glib/proplist.c b/src/lua_libpulse_glib/proplist.c new file mode 100644 index 0000000..35c6a91 --- /dev/null +++ b/src/lua_libpulse_glib/proplist.c @@ -0,0 +1,214 @@ +#include "proplist.h" + +#include + +// Creates a Lua userdatum from/for a PulseAudio proplist. +// +// The provided proplist will be `pa_proplist_copy()`ed to pass memory management over +// to the garbage collector. +// +// @return[type=PropList] +int proplist_to_lua(lua_State* L, pa_proplist* pa_plist) { + proplist* plist = lua_newuserdata(L, sizeof(proplist)); + if (pa_plist == NULL) { + lua_pushfstring(L, "Failed to allocate proplist userdata"); + return lua_error(L); + } + luaL_getmetatable(L, LUA_PA_PROPLIST); + lua_setmetatable(L, -2); + + plist->plist = pa_proplist_copy(pa_plist); + + return 1; +} + + +int proplist_new(lua_State* L) { + pa_proplist* pa_plist = pa_proplist_new(); + if (pa_plist == NULL) { + lua_pushfstring(L, "Failed to allocate PulseAudio proplist"); + return lua_error(L); + } + + return proplist_to_lua(L, pa_plist); +} + + +int proplist_from_string(lua_State* L) { + const char* str = luaL_checkstring(L, 1); + pa_proplist* pa_plist = pa_proplist_from_string(str); + + return proplist_to_lua(L, pa_plist); +} + + +int proplist_key_valid(lua_State* L) { + const char* key = luaL_checkstring(L, 1); + int valid = pa_proplist_key_valid(key); + lua_pushboolean(L, valid); + return 1; +} + + +int proplist_isempty(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + int empty = pa_proplist_isempty(plist->plist); + lua_pushboolean(L, empty); + return 1; +} + + +int proplist_tostring_sep(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + const char* sep = luaL_checkstring(L, 2); + const char* str = pa_proplist_to_string_sep(plist->plist, sep); + lua_pushstring(L, str); + pa_xfree((void*) str); + return 1; +} + + +int proplist_clear(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + pa_proplist_clear(plist->plist); + return 0; +} + + +int proplist_contains(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + const char* key = luaL_checkstring(L, 2); + if (!pa_proplist_key_valid(key)) { + return luaL_error(L, "invalid key for proplist"); + } + + int contains = pa_proplist_contains(plist->plist, key); + if (contains < 0) { + return luaL_error(L, "failed to check if proplist contains the key"); + } else { + lua_pushboolean(L, contains); + } + + return 1; +} + + +int proplist_copy(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + pa_proplist* other = pa_proplist_copy(plist->plist); + + return proplist_to_lua(L, other); +} + + +// Metatable functions + + +// Accesses the value at the given string key. +// +// This functions very similar to a regular hash table. +// +// Numeric indices/keys are not supported. +// +// Will return `nil` if there is no value or if it is not valid UTF-8. +// Arbitrary data from `pa_proplist_get()` is currently not supported. +// +// @param[type=string] key The index to access. +// @return[type=string|nil] The data at the given index. +int proplist__index(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + const char* key = luaL_checkstring(L, 2); + if (!pa_proplist_key_valid(key)) { + return luaL_error(L, "invalid key for proplist"); + } + + if (!pa_proplist_contains(plist->plist, key)) { + lua_pushnil(L); + return 1; + } + + const char* value = pa_proplist_gets(plist->plist, key); + if (value == NULL) { + lua_pushnil(L); + } else { + lua_pushstring(L, value); + } + + return 1; +} + + +// Sets or overwrites the value at the given key. +// +// Passing `nil` as value will unset the key. +// +// For both keys and values only strings are supported. +// Numeric indices or binary data values (as in `pa_proplist_set()`) are not available. +// +// @param[type=string] key The index to write to. +// @param[type=string|nil] value The value to write. +int proplist__newindex(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + const char* key = luaL_checkstring(L, 2); + + if (lua_isnil(L, 3)) { + if (pa_proplist_unset(plist->plist, key) < 0) { + // TODO: Get last error. Need to get access to the current context for + // this. + return luaL_error(L, "failed to unset key %s", key); + } + } else { + const char* value = luaL_checkstring(L, 3); + if (pa_proplist_sets(plist->plist, key, value) < 0) { + return luaL_error(L, "failed to set value for key %s", key); + } + } + + return 0; +} + + +// Frees the internal proplist. +int proplist__gc(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + pa_proplist_free(plist->plist); + return 0; +} + + +// Gets the size of the proplist. +int proplist__len(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + unsigned len = pa_proplist_size(plist->plist); + lua_pushinteger(L, len); + return 1; +} + + +// Compares two proplists for equality. +// +// Proplists are equal if they contain the same keys with the same values. +// +// @param[type=PropList] other The proplist to compare against. +// @return[type=boolean] +int proplist__eq(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + proplist* other = luaL_checkudata(L, 2, LUA_PA_PROPLIST); + int equal = pa_proplist_equal(plist->plist, other->plist); + lua_pushboolean(L, equal); + return 1; +} + + +// Creates a string representation. +// +// This adds a newline character as separator and as final character. +// +// @return[type=string] +int proplist__tostring(lua_State* L) { + proplist* plist = luaL_checkudata(L, 1, LUA_PA_PROPLIST); + char* str = pa_proplist_to_string(plist->plist); + lua_pushstring(L, str); + pa_xfree((void*) str); + return 1; +} diff --git a/src/lua_libpulse_glib/proplist.h b/src/lua_libpulse_glib/proplist.h new file mode 100644 index 0000000..bacb3ed --- /dev/null +++ b/src/lua_libpulse_glib/proplist.h @@ -0,0 +1,316 @@ +/** Bindings for PulseAudio's property lists. + * + * Basic operations are mapped to Lua table operations: + * + * - get a value: `plist[key]` + * - set a value: `plist[key] = value` + * - get the size: `#plist` + * - get default string presentation: `tostring(plist)` + * - equality: `plist == other` + * + * Additional operations are exposed as methods, as documented below. + * + * @module pulseaudio.proplist + */ +#pragma once + +#include "lua_util.h" + +#include +#include +#include +#include + +#define LUA_PA_PROPLIST "pulseaudio.proplist" + + +typedef struct proplist { + pa_proplist* plist; +} proplist; + + +/** A list of well-known keys. These will likely be used by other consumers + * of PulseAudio, so should be preferred for interoperatibility. + * + * See [proplist.h](https://freedesktop.org/software/pulseaudio/doxygen/proplist_8h.html) for details on + * these values. + * + * local proplist = require("pulseaudio.proplist") + * proplist.is_key_valid(proplist.MEDIA_NAME) -- true + * print(proplist.MEDIA_NAME) -- media.name + * + * @table pulseaudio.proplist + * @field MEDIA_NAME media.name + * @field MEDIA_TITLE media.title + * @field MEDIA_ARTIST media.artist + * @field MEDIA_COPYRIGHT media.copyright + * @field MEDIA_SOFTWARE media.software + * @field MEDIA_LANGUAGE media.language + * @field MEDIA_FILENAME media.filename + * @field MEDIA_ICON media.icon + * @field MEDIA_ICON_NAME media.icon_name + * @field MEDIA_ROLE media.role + * @field FILTER_WANT filter.want + * @field FILTER_APPLY filter.apply + * @field FILTER_SUPPRESS filter.suppress + * @field EVENT_ID event.id + * @field EVENT_DESCRIPTION event.description + * @field EVENT_MOUSE_X event.mouse.x + * @field EVENT_MOUSE_Y event.mouse.y + * @field EVENT_MOUSE_HPOS event.mouse.hpos + * @field EVENT_MOUSE_VPOS event.mouse.vpos + * @field EVENT_MOUSE_BUTTON event.mouse.button + * @field WINDOW_NAME window.name + * @field WINDOW_ID window.id + * @field WINDOW_ICON window.icon + * @field WINDOW_ICON_NAME window.icon_name + * @field WINDOW_X window.x + * @field WINDOW_Y window.y + * @field WINDOW_WIDTH window.width + * @field WINDOW_HEIGHT window.height + * @field WINDOW_HPOS window.hpos + * @field WINDOW_VPOS window.vpos + * @field WINDOW_DESKTOP window.desktop + * @field WINDOW_X11_DISPLAY window.x11.display + * @field WINDOW_X11_SCREEN window.x11.screen + * @field WINDOW_X11_MONITOR window.x11.monitor + * @field WINDOW_X11_XID window.x11.xid + * @field APPLICATION_NAME application.name + * @field APPLICATION_ID application.id + * @field APPLICATION_VERSION application.version + * @field APPLICATION_ICON application.icon + * @field APPLICATION_ICON_NAME application.icon_name + * @field APPLICATION_LANGUAGE application.language + * @field APPLICATION_PROCESS_ID application.process.id + * @field APPLICATION_PROCESS_BINARY application.process.binary + * @field APPLICATION_PROCESS_USER application.process.user + * @field APPLICATION_PROCESS_HOST application.process.host + * @field APPLICATION_PROCESS_MACHINE_ID application.process.machine_id + * @field APPLICATION_PROCESS_SESSION_ID application.process.session_id + * @field DEVICE_STRING device.string + * @field DEVICE_API device.api + * @field DEVICE_DESCRIPTION device.description + * @field DEVICE_BUS_PATH device.bus_path + * @field DEVICE_SERIAL device.serial + * @field DEVICE_VENDOR_ID device.vendor.id + * @field DEVICE_VENDOR_NAME device.vendor.name + * @field DEVICE_PRODUCT_ID device.product.id + * @field DEVICE_PRODUCT_NAME device.product.name + * @field DEVICE_CLASS device.class + * @field DEVICE_FORM_FACTOR device.form_factor + * @field DEVICE_BUS device.bus + * @field DEVICE_ICON device.icon + * @field DEVICE_ICON_NAME device.icon_name + * @field DEVICE_ACCESS_MODE device.access_mode + * @field DEVICE_MASTER_DEVICE device.master_device + * @field DEVICE_BUFFERING_BUFFER_SIZE device.buffering.buffer_size + * @field DEVICE_BUFFERING_FRAGMENT_SIZE device.buffering.fragment_size + * @field DEVICE_PROFILE_NAME device.profile.name + * @field DEVICE_INTENDED_ROLES device.intended_roles + * @field DEVICE_PROFILE_DESCRIPTION device.profile.description + * @field MODULE_AUTHOR module.author + * @field MODULE_DESCRIPTION module.description + * @field MODULE_USAGE module.usage + * @field MODULE_VERSION module.version + * @field FORMAT_SAMPLE_FORMAT format.sample_format + * @field FORMAT_RATE format.rate + * @field FORMAT_CHANNELS format.channels + * @field FORMAT_CHANNEL_MAP format.channel_map + * @field CONTEXT_FORCE_DISABLE_SHM context.force.disable.shm + * @field BLUETOOTH_CODEC bluetooth.codec + */ + + +/// Constructor functions. +/// @section constructors + + +/** Creates a new, empty property list. + * + * @function new + * @return[type=PropList] + */ +int proplist_new(lua_State*); + +/** Parses a string into a @{PropList}. + * + * @function from_string + * @param[type=string] str The string to parse. + * @return[type=PropList] + */ +int proplist_from_string(lua_State*); + + +/// Static functions +/// @section static + + +/** Checks if the given string is a valid key. + * + * @function is_key_valid + * @param[type=string] key The string to check. + * @return[type=boolean] + */ +int proplist_key_valid(lua_State*); + + +// Internal functions + +int proplist_to_lua(lua_State*, pa_proplist*); +int proplist__index(lua_State*); +int proplist__newindex(lua_State*); +int proplist__gc(lua_State*); +int proplist__len(lua_State*); +int proplist__eq(lua_State*); +int proplist__tostring(lua_State*); + + +/// Methods +/// @type PropList + + +/** Checks if the proplist is empty. + * + * @function is_empty + * @return[type=boolean] + */ +int proplist_isempty(lua_State*); + +/** Creates a string representation with a custom separator. + * + * @function tostring_sep + * @return[type=string] + */ +int proplist_tostring_sep(lua_State*); + +/** Removes all keys from the proplist + * + * @function clear + */ +int proplist_clear(lua_State*); + +/** Checks if the proplist contains the given key. + * + * @function contains + * @param[type=string] key The key to check for. + * @return[type=boolean] + */ +int proplist_contains(lua_State*); + +/** Duplicates the proplist. + * + * @function copy + * @return[type=proplist] + */ +int proplist_copy(lua_State*); + + +static const struct luaL_Reg proplist_f[] = { + {"clear", proplist_clear }, + { "contains", proplist_contains }, + { "copy", proplist_copy }, + { "is_empty", proplist_isempty }, + { "tostring_sep", proplist_tostring_sep}, + { NULL, NULL } +}; + + +static const struct luaL_Reg proplist_mt[] = { + {"__gc", proplist__gc }, + { "__len", proplist__len }, + { "__tostring", proplist__tostring}, + { "__eq", proplist__eq }, + { "__index", proplist__index }, + { "__newindex", proplist__newindex}, + { NULL, NULL } +}; + + +static const struct luaL_Reg proplist_lib[] = { + {"new", proplist_new }, + { "is_key_valid", proplist_key_valid }, + { "from_string", proplist_from_string}, + { NULL, NULL } +}; + + +static const struct luaU_enumfield proplist_enum[] = { + {"MEDIA_TITLE", PA_PROP_MEDIA_TITLE }, + { "MEDIA_ARTIST", PA_PROP_MEDIA_ARTIST }, + { "MEDIA_COPYRIGHT", PA_PROP_MEDIA_COPYRIGHT }, + { "MEDIA_SOFTWARE", PA_PROP_MEDIA_SOFTWARE }, + { "MEDIA_LANGUAGE", PA_PROP_MEDIA_LANGUAGE }, + { "MEDIA_FILENAME", PA_PROP_MEDIA_FILENAME }, + { "MEDIA_ICON", PA_PROP_MEDIA_ICON }, + { "MEDIA_ICON_NAME", PA_PROP_MEDIA_ICON_NAME }, + { "MEDIA_ROLE", PA_PROP_MEDIA_ROLE }, + { "FILTER_WANT", PA_PROP_FILTER_WANT }, + { "FILTER_APPLY", PA_PROP_FILTER_APPLY }, + { "FILTER_SUPPRESS", PA_PROP_FILTER_SUPPRESS }, + { "EVENT_ID", PA_PROP_EVENT_ID }, + { "EVENT_DESCRIPTION", PA_PROP_EVENT_DESCRIPTION }, + { "EVENT_MOUSE_X", PA_PROP_EVENT_MOUSE_X }, + { "EVENT_MOUSE_Y", PA_PROP_EVENT_MOUSE_Y }, + { "EVENT_MOUSE_HPOS", PA_PROP_EVENT_MOUSE_HPOS }, + { "EVENT_MOUSE_VPOS", PA_PROP_EVENT_MOUSE_VPOS }, + { "EVENT_MOUSE_BUTTON", PA_PROP_EVENT_MOUSE_BUTTON }, + { "WINDOW_NAME", PA_PROP_WINDOW_NAME }, + { "WINDOW_ID", PA_PROP_WINDOW_ID }, + { "WINDOW_ICON", PA_PROP_WINDOW_ICON }, + { "WINDOW_ICON_NAME", PA_PROP_WINDOW_ICON_NAME }, + { "WINDOW_X", PA_PROP_WINDOW_X }, + { "WINDOW_Y", PA_PROP_WINDOW_Y }, + { "WINDOW_WIDTH", PA_PROP_WINDOW_WIDTH }, + { "WINDOW_HEIGHT", PA_PROP_WINDOW_HEIGHT }, + { "WINDOW_HPOS", PA_PROP_WINDOW_HPOS }, + { "WINDOW_VPOS", PA_PROP_WINDOW_VPOS }, + { "WINDOW_DESKTOP", PA_PROP_WINDOW_DESKTOP }, + { "WINDOW_X11_DISPLAY", PA_PROP_WINDOW_X11_DISPLAY }, + { "WINDOW_X11_SCREEN", PA_PROP_WINDOW_X11_SCREEN }, + { "WINDOW_X11_MONITOR", PA_PROP_WINDOW_X11_MONITOR }, + { "WINDOW_X11_XID", PA_PROP_WINDOW_X11_XID }, + { "APPLICATION_NAME", PA_PROP_APPLICATION_NAME }, + { "APPLICATION_ID", PA_PROP_APPLICATION_ID }, + { "APPLICATION_VERSION", PA_PROP_APPLICATION_VERSION }, + { "APPLICATION_ICON", PA_PROP_APPLICATION_ICON }, + { "APPLICATION_ICON_NAME", PA_PROP_APPLICATION_ICON_NAME }, + { "APPLICATION_LANGUAGE", PA_PROP_APPLICATION_LANGUAGE }, + { "APPLICATION_PROCESS_ID", PA_PROP_APPLICATION_PROCESS_ID }, + { "APPLICATION_PROCESS_BINARY", PA_PROP_APPLICATION_PROCESS_BINARY }, + { "APPLICATION_PROCESS_USER", PA_PROP_APPLICATION_PROCESS_USER }, + { "APPLICATION_PROCESS_HOST", PA_PROP_APPLICATION_PROCESS_HOST }, + { "APPLICATION_PROCESS_MACHINE_ID", PA_PROP_APPLICATION_PROCESS_MACHINE_ID}, + { "APPLICATION_PROCESS_SESSION_ID", PA_PROP_APPLICATION_PROCESS_SESSION_ID}, + { "DEVICE_STRING", PA_PROP_DEVICE_STRING }, + { "DEVICE_API", PA_PROP_DEVICE_API }, + { "DEVICE_DESCRIPTION", PA_PROP_DEVICE_DESCRIPTION }, + { "DEVICE_BUS_PATH", PA_PROP_DEVICE_BUS_PATH }, + { "DEVICE_SERIAL", PA_PROP_DEVICE_SERIAL }, + { "DEVICE_VENDOR_ID", PA_PROP_DEVICE_VENDOR_ID }, + { "DEVICE_VENDOR_NAME", PA_PROP_DEVICE_VENDOR_NAME }, + { "DEVICE_PRODUCT_ID", PA_PROP_DEVICE_PRODUCT_ID }, + { "DEVICE_PRODUCT_NAME", PA_PROP_DEVICE_PRODUCT_NAME }, + { "DEVICE_CLASS", PA_PROP_DEVICE_CLASS }, + { "DEVICE_FORM_FACTOR", PA_PROP_DEVICE_FORM_FACTOR }, + { "DEVICE_BUS", PA_PROP_DEVICE_BUS }, + { "DEVICE_ICON", PA_PROP_DEVICE_ICON }, + { "DEVICE_ICON_NAME", PA_PROP_DEVICE_ICON_NAME }, + { "DEVICE_ACCESS_MODE", PA_PROP_DEVICE_ACCESS_MODE }, + { "DEVICE_MASTER_DEVICE", PA_PROP_DEVICE_MASTER_DEVICE }, + { "DEVICE_BUFFERING_BUFFER_SIZE", PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE }, + { "DEVICE_BUFFERING_FRAGMENT_SIZE", PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE}, + { "DEVICE_PROFILE_NAME", PA_PROP_DEVICE_PROFILE_NAME }, + { "DEVICE_INTENDED_ROLES", PA_PROP_DEVICE_INTENDED_ROLES }, + { "DEVICE_PROFILE_DESCRIPTION", PA_PROP_DEVICE_PROFILE_DESCRIPTION }, + { "MODULE_AUTHOR", PA_PROP_MODULE_AUTHOR }, + { "MODULE_DESCRIPTION", PA_PROP_MODULE_DESCRIPTION }, + { "MODULE_USAGE", PA_PROP_MODULE_USAGE }, + { "MODULE_VERSION", PA_PROP_MODULE_VERSION }, + { "FORMAT_SAMPLE_FORMAT", PA_PROP_FORMAT_SAMPLE_FORMAT }, + { "FORMAT_RATE", PA_PROP_FORMAT_RATE }, + { "FORMAT_CHANNELS", PA_PROP_FORMAT_CHANNELS }, + { "FORMAT_CHANNEL_MAP", PA_PROP_FORMAT_CHANNEL_MAP }, + { "CONTEXT_FORCE_DISABLE_SHM", PA_PROP_CONTEXT_FORCE_DISABLE_SHM }, + { "BLUETOOTH_CODEC", PA_PROP_BLUETOOTH_CODEC }, + { NULL, NULL } +}; diff --git a/src/lua_libpulse_glib/pulseaudio.c b/src/lua_libpulse_glib/pulseaudio.c index 05eedb7..666305b 100644 --- a/src/lua_libpulse_glib/pulseaudio.c +++ b/src/lua_libpulse_glib/pulseaudio.c @@ -1,53 +1,42 @@ -/// libpulse bindings. -// -// @module pulseaudio +#include "pulseaudio.h" +#include "context.h" +#include "lua_util.h" +#include "proplist.h" +#include "volume.h" + +#include #include #include -#include #include -#include "pulseaudio.h" -#include "context.h" -#define LUA_MOD_EXPORT extern #define LUA_PULSEAUDIO "pulseaudio" - #if LUA_VERSION_NUM <= 501 // Shamelessly copied from Lua 5.3 source. // TODO: What's the official way to do this in 5.1? -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { +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? */ + 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 */ + 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_pushcclosure(L, l->func, nup); /* closure with those upvalues */ } lua_setfield(L, -(nup + 2), l->name); } - lua_pop(L, nup); /* remove upvalues */ + lua_pop(L, nup); /* remove upvalues */ } -#define luaL_newlib(L,l) (luaL_register(L,LUA_PULSEAUDIO,l)) +#define luaL_newlib(L, l) (luaL_register(L, LUA_PULSEAUDIO, l)) #endif -/** - * Creates a new PulseAudio object. - * - * The API requires a GLib Main Context internally. Currently, only the default context - * is supported. - * - * @return[type=PulseAudio] - */ -int -pulseaudio_new(lua_State* L) -{ +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?"); @@ -55,7 +44,7 @@ pulseaudio_new(lua_State* L) return 0; } - pulseaudio* pa = lua_newuserdata (L, sizeof(pulseaudio)); + pulseaudio* pa = lua_newuserdata(L, sizeof(pulseaudio)); if (!pa) { return luaL_error(L, "failed to create pulseaudio userdata"); } @@ -68,12 +57,10 @@ pulseaudio_new(lua_State* L) } -/** +/* * Proxies table index operations to our metatable. */ -int -pulseaudio__index(lua_State* L) -{ +int pulseaudio__index(lua_State* L) { const char* index = luaL_checkstring(L, 2); luaL_getmetatable(L, LUA_PULSEAUDIO); lua_getfield(L, -1, index); @@ -81,28 +68,98 @@ pulseaudio__index(lua_State* L) } -/** +/* * Free the PulseAudio object */ -int -pulseaudio__gc(lua_State* L) -{ +int pulseaudio__gc(lua_State* L) { pulseaudio* pa = luaL_checkudata(L, 1, LUA_PULSEAUDIO); pa_glib_mainloop_free(pa->mainloop); return 0; } -int -pulseaudio_new_context(lua_State* L) -{ +int pulseaudio_new_context(lua_State* L) { pulseaudio* pa = luaL_checkudata(L, 1, LUA_PULSEAUDIO); return context_new(L, pa_glib_mainloop_get_api(pa->mainloop)); } -LUA_MOD_EXPORT int luaopen_lua_libpulse_glib(lua_State* L) -{ +void createlib_volume(lua_State* L) { + luaL_newmetatable(L, LUA_PA_VOLUME); + + lua_createtable(L, 0, sizeof volume_f / sizeof volume_f[0]); + luaL_setfuncs(L, volume_f, 0); + lua_setfield(L, -2, "__index"); + + luaL_setfuncs(L, volume_mt, 0); + +#if LUA_VERSION_NUM <= 501 + luaL_register(L, LUA_PA_VOLUME, volume_lib); +#else + luaL_newlib(L, volume_lib); +#endif + lua_setmetatable(L, -2); +} + + +void createlib_proplist(lua_State* L) { + luaL_newmetatable(L, LUA_PA_PROPLIST); + + lua_createtable(L, 0, sizeof proplist_f / sizeof proplist_f[0]); + luaL_setfuncs(L, proplist_f, 0); + lua_setfield(L, -2, "__index"); + + luaL_setfuncs(L, proplist_mt, 0); + +#if LUA_VERSION_NUM <= 501 + luaL_register(L, LUA_PA_PROPLIST, proplist_lib); +#else + luaL_newlib(L, proplist_lib); +#endif + + // Create a metatable with an `__index` table for read-only enum fields. + lua_createtable(L, 0, 1); + + lua_createtable(L, 0, sizeof proplist_enum / sizeof proplist_enum[0]); + for (int i = 0; proplist_enum[i].name != NULL; ++i) { + lua_pushstring(L, proplist_enum[i].value); + lua_setfield(L, -2, proplist_enum[i].name); + } + + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); +} + + +void createlib_context(lua_State* L) { + luaL_newmetatable(L, LUA_PA_CONTEXT); + + lua_createtable(L, 0, sizeof context_f / sizeof context_f[0]); + luaL_setfuncs(L, context_f, 0); + lua_setfield(L, -2, "__index"); + + luaL_setfuncs(L, context_mt, 0); +} + + +void createlib_pulseaudio(lua_State* L) { + luaL_newmetatable(L, LUA_PULSEAUDIO); + + lua_createtable(L, 0, sizeof pulseaudio_f / sizeof pulseaudio_f[0]); + luaL_setfuncs(L, pulseaudio_f, 0); + lua_setfield(L, -2, "__index"); + + luaL_setfuncs(L, pulseaudio_mt, 0); + +#if LUA_VERSION_NUM <= 501 + luaL_register(L, LUA_PULSEAUDIO, pulseaudio_lib); +#else + luaL_newlib(L, pulseaudio_lib); +#endif +} + + +LUA_MOD_EXPORT int luaopen_lua_libpulse_glib(lua_State* L) { // Create a table to store callback refs in, stored in the Lua registry lua_pushstring(L, LUA_PULSEAUDIO); lua_newtable(L); @@ -111,12 +168,9 @@ LUA_MOD_EXPORT int luaopen_lua_libpulse_glib(lua_State* L) lua_settable(L, -3); lua_rawset(L, LUA_REGISTRYINDEX); - luaL_newmetatable(L, LUA_PA_CONTEXT); - luaL_setfuncs(L, context_mt, 0); - - luaL_newmetatable(L, LUA_PULSEAUDIO); - luaL_setfuncs(L, pulseaudio_mt, 0); - - luaL_newlib(L, pulseaudio_lib); + createlib_volume(L); + createlib_context(L); + createlib_proplist(L); + createlib_pulseaudio(L); return 1; } diff --git a/src/lua_libpulse_glib/pulseaudio.h b/src/lua_libpulse_glib/pulseaudio.h index dd18fe0..e329771 100644 --- a/src/lua_libpulse_glib/pulseaudio.h +++ b/src/lua_libpulse_glib/pulseaudio.h @@ -1,17 +1,15 @@ +/** Bindings for PulseAudio's libpulse, using the GLib Main Loop. + * + * @module pulseaudio + */ #pragma once -#include "lua.h" #include "lauxlib.h" +#include "lua.h" + #include -#ifdef _WIN32 -#define LUA_MOD_EXPORT __declspec(dllexport) -#else -#define LUA_MOD_EXPORT extern -#endif - - -#define LUA_PULSEAUDIO "pulseaudio" +#define LUA_PULSEAUDIO "pulseaudio" #define LUA_PA_REGISTRY "pulseaudio.registry" @@ -20,25 +18,43 @@ typedef struct pulseaudio { } pulseaudio; -int -pulseaudio_new(lua_State*); -int -pulseaudio__gc(lua_State*); -int -pulseaudio__index(lua_State*); -int -pulseaudio_new_context(lua_State*); +/** Creates a new PulseAudio object. + * + * @function new + * @return[type=PulseAudio] + */ +int pulseaudio_new(lua_State*); -static const struct luaL_Reg pulseaudio_mt [] = { - {"__index", pulseaudio__index}, +int pulseaudio__gc(lua_State*); + + +/// PulseAudio API +/// @type PulseAudio + + +/** Creates a new PulseAudio context + * + * @function context + * @tparam string name The application name. + * @return[type=Context] + */ +int pulseaudio_new_context(lua_State*); + + +static const struct luaL_Reg pulseaudio_mt[] = { {"__gc", pulseaudio__gc}, + { NULL, NULL } +}; + + +static const struct luaL_Reg pulseaudio_f[] = { {"context", pulseaudio_new_context}, - {NULL, NULL} + { NULL, NULL } }; -static const struct luaL_Reg pulseaudio_lib [] = { +static const struct luaL_Reg pulseaudio_lib[] = { {"new", pulseaudio_new}, - {NULL, NULL} + { NULL, NULL } }; diff --git a/src/lua_libpulse_glib/volume.c b/src/lua_libpulse_glib/volume.c new file mode 100644 index 0000000..73c3466 --- /dev/null +++ b/src/lua_libpulse_glib/volume.c @@ -0,0 +1,307 @@ +#include "volume.h" + +#include +#include +#include +#include + + +int volume_to_lua(lua_State* L, const pa_cvolume* pa_volume) { + volume_t* volume = lua_newuserdata(L, sizeof(volume_t)); + if (pa_volume == NULL) { + lua_pushfstring(L, "Failed to allocate volume userdata"); + return lua_error(L); + } + luaL_getmetatable(L, LUA_PA_VOLUME); + lua_setmetatable(L, -2); + + volume->inner = *pa_volume; + return 1; +} + + +// When the value is a plain Lua table, a new `pa_cvolume` is allocated and the caller is +// responsible of freeing it with `pa_xfree`. +// If a userdata is passed instead, memory is owned by Lua and not be freed. +// TODO: Maybe construct userdata from the table, so that memory management is always handled +// by GC. Makes this easier to use. But only do so after the current version has been committed +// once, just so it stays available. +pa_cvolume* volume_from_lua(lua_State* L, int index) { + switch (lua_type(L, 2)) { + case LUA_TTABLE: { + uint8_t channels = (uint8_t) lua_objlen(L, index); + if (channels > PA_CHANNELS_MAX) { + channels = PA_CHANNELS_MAX; + } + + pa_cvolume* volume = pa_xnew(pa_cvolume, 1); + volume->channels = channels; + + for (int i = 0; i < channels; ++i) { + lua_pushinteger(L, i + 1); + lua_gettable(L, index); + pa_volume_t vol = (pa_volume_t) luaL_checkinteger(L, -1); + volume->values[i] = PA_CLAMP_VOLUME(vol); + lua_pop(L, 1); + } + + return volume; + } + case LUA_TUSERDATA: { + volume_t* volume = luaL_checkudata(L, index, LUA_PA_VOLUME); + return &volume->inner; + } + default: { + luaL_argerror(L, index, "expected table or userdata"); + return NULL; + } + } +} + + +int volume__len(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_pushinteger(L, volume->inner.channels); + return 1; +} + + +int volume__eq(lua_State* L) { + volume_t* left = luaL_checkudata(L, 1, LUA_PA_VOLUME); + volume_t* right = luaL_checkudata(L, 2, LUA_PA_VOLUME); + lua_pushboolean(L, pa_cvolume_equal(&left->inner, &right->inner)); + return 1; +} + + +int volume__index(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + int index = luaL_checkint(L, 2); + luaL_argcheck(L, index >= 1 && index <= (PA_CHANNELS_MAX + 1), 2, "channel index out of bounds"); + lua_pushinteger(L, volume->inner.values[index - 1]); + return 1; +} + + +int volume__newindex(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer index = luaL_checkinteger(L, 2); + lua_Integer value = luaL_checkinteger(L, 3); + luaL_argcheck(L, index >= 1 && index <= (PA_CHANNELS_MAX + 1), 2, "channel index out of bounds"); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 3, "volume value is invalid"); + volume->inner.values[index - 1] = value; + return 0; +} + + +int volume__tostring(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + char s[PA_CVOLUME_SNPRINT_MAX]; + pa_cvolume_snprint(s, PA_CVOLUME_SNPRINT_MAX, &volume->inner); + lua_pushstring(L, s); + return 1; +} + +int volume_is_valid(lua_State* L) { + // Lua's `checkudata` throws an error, and catching that is expensive. + // So we have to manually implement the check. + volume_t* volume = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_PA_VOLUME); + bool is_userdata = volume != NULL && lua_getmetatable(L, 1) && lua_rawequal(L, -1, -2); + // Remove the two metatables + lua_pop(L, 2); + lua_pushboolean(L, is_userdata && pa_cvolume_valid(&volume->inner)); + return 1; +} + + +int volume_channels_equal_to(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer value = luaL_checkinteger(L, 2); + + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 2, "volume out of bounds"); + + lua_pushboolean(L, pa_cvolume_channels_equal_to(&volume->inner, (pa_volume_t) value)); + return 1; +} + + +int volume_is_muted(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_pushboolean(L, pa_cvolume_is_muted(&volume->inner)); + return 1; +} + + +int volume_is_norm(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_pushboolean(L, pa_cvolume_is_norm(&volume->inner)); + return 1; +} + + +int volume_set_channels(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer channels = luaL_checkinteger(L, 2); + lua_Integer value = luaL_checkinteger(L, 3); + + luaL_argcheck(L, channels >= 0 && channels <= PA_CHANNELS_MAX, 2, "channel count out of bounds"); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 3, "volume out of bounds"); + + pa_cvolume_set(&volume->inner, (unsigned int) channels, (pa_volume_t) value); + return 0; +} + + +int volume_set(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer index = luaL_checkinteger(L, 2) - 1; + lua_Integer value = luaL_checkinteger(L, 3); + + luaL_argcheck(L, index >= 0 && index <= PA_CHANNELS_MAX, 2, "channel index out of bounds"); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 3, "volume out of bounds"); + + volume->inner.values[index] = (pa_volume_t) value; + return 0; +} + + +int volume_get(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer index = luaL_checkinteger(L, 2) - 1; + + luaL_argcheck(L, index > 0 && index < volume->inner.channels, 2, "channel index out of bounds"); + + lua_pushinteger(L, volume->inner.values[index]); + return 1; +} + + +int volume_reset(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer channels = luaL_checkinteger(L, 2); + luaL_argcheck(L, channels >= 0 && channels <= PA_CHANNELS_MAX, 2, "channel count out of bounds"); + pa_cvolume_reset(&volume->inner, channels); + return 0; +} + + +int volume_mute(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer channels = luaL_checkinteger(L, 2); + luaL_argcheck(L, channels >= 0 && channels <= PA_CHANNELS_MAX, 2, "channel count out of bounds"); + pa_cvolume_mute(&volume->inner, channels); + return 0; +} + + +int volume_avg(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_pushinteger(L, pa_cvolume_avg(&volume->inner)); + return 1; +} + + +int volume_min(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_pushinteger(L, pa_cvolume_min(&volume->inner)); + return 1; +} + + +int volume_max(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_pushinteger(L, pa_cvolume_max(&volume->inner)); + return 1; +} + + +int volume_inc(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer value = luaL_checkinteger(L, 2); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 2, "volume out of bounds"); + if (!pa_cvolume_inc(&volume->inner, (pa_volume_t) value)) { + return luaL_error(L, "failed to increase volume"); + } + + return 0; +} + + +int volume_dec(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer value = luaL_checkinteger(L, 2); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 2, "volume out of bounds"); + if (!pa_cvolume_dec(&volume->inner, (pa_volume_t) value)) { + return luaL_error(L, "failed to decrease volume"); + } + + return 0; +} + + +int volume_scale(lua_State* L) { + volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); + lua_Integer value = luaL_checkinteger(L, 2); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 2, "volume out of bounds"); + if (!pa_cvolume_scale(&volume->inner, (pa_volume_t) value)) { + return luaL_error(L, "failed to scale volume"); + } + + return 0; +} + + +int volume_multiply(lua_State* L) { + volume_t* left = luaL_checkudata(L, 1, LUA_PA_VOLUME); + + switch (lua_type(L, 2)) { + case LUA_TNUMBER: { + lua_Integer value = luaL_checkinteger(L, 2); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 2, "volume out of bounds"); + if (!pa_sw_cvolume_multiply_scalar(&left->inner, &left->inner, (pa_volume_t) value)) { + return luaL_error(L, "failed to multiply volume"); + } + + return 0; + } + case LUA_TUSERDATA: { + volume_t* right = luaL_checkudata(L, 2, LUA_PA_VOLUME); + if (!pa_sw_cvolume_multiply(&left->inner, &left->inner, &right->inner)) { + return luaL_error(L, "failed to multiply volume"); + } + + return 0; + } + default: { + return luaL_argerror(L, 2, "expected number or userdata"); + } + } +} + +int volume_divide(lua_State* L) { + volume_t* left = luaL_checkudata(L, 1, LUA_PA_VOLUME); + + switch (lua_type(L, 2)) { + case LUA_TNUMBER: { + lua_Integer value = luaL_checkinteger(L, 2); + luaL_argcheck(L, PA_VOLUME_IS_VALID(value), 2, "volume out of bounds"); + if (!pa_sw_cvolume_divide_scalar(&left->inner, &left->inner, (pa_volume_t) value)) { + return luaL_error(L, "failed to divide volume"); + } + + return 0; + } + case LUA_TUSERDATA: { + volume_t* right = luaL_checkudata(L, 2, LUA_PA_VOLUME); + if (!pa_sw_cvolume_divide(&left->inner, &left->inner, &right->inner)) { + return luaL_error(L, "failed to divide volume"); + } + + return 0; + } + default: { + return luaL_argerror(L, 2, "expected number or userdata"); + } + } +} diff --git a/src/lua_libpulse_glib/volume.h b/src/lua_libpulse_glib/volume.h new file mode 100644 index 0000000..01f8631 --- /dev/null +++ b/src/lua_libpulse_glib/volume.h @@ -0,0 +1,237 @@ +/** Bindings for libpulse's `pa_cvolume`. + * + * Contrary to libpulse, methods that change the a @{Volume} object generally don't return anything, but + * instead change the instance itself. + * + * @module pulseaudio.volume + */ +#ifndef volume_h_INCLUDED +#define volume_h_INCLUDED + +#include +#include +#include + +#define LUA_PA_VOLUME "pulseaudio.volume" + + +typedef struct volume_t { + pa_cvolume inner; +} volume_t; + + +/* Creates a Lua userdatum from/for a PulseAudio volume. + * + * Control over the `pa_plist`'s memory has to be taken over by this function, + * to enable integration into Lua's garbage collection. + * + * @function volume_to_lua + * @treturn Volume + */ +int volume_to_lua(lua_State*, const pa_cvolume*); + +/* Creates a pa_cvolume from Lua userdata + */ +pa_cvolume* volume_from_lua(lua_State*, int); + +/* Implements the `#` length operator. + * This simply proxies to the `.channels` value. + */ +int volume__len(lua_State*); +int volume__eq(lua_State*); +int volume__tostring(lua_State*); +int volume__index(lua_State*); +int volume__newindex(lua_State*); + + +/// Static Functions +/// @section static + + +/** Checks whether a value is a valid @{Volume}. + * + * @function is_valid + * @tparam any value The value to check + * @treturn boolean + */ +int volume_is_valid(lua_State*); + +/// Volume +/// @type Volume + +/** Returns the average volume over all channels. + * + * @function Volume:avg + * @treturn number + */ +int volume_avg(lua_State*); + +/** Returns `true` if the volume of all channels is equal to the specified value. + * + * @function Volume:channels_equal_to + * @tparam number value Volume to compare to + * @treturn boolean + */ +int volume_channels_equal_to(lua_State*); + +/** Decreases the volume by the given amount. + * + * The proportions between the channels are kept. + * + * @function Volume:dec + * @tparam number value The value to decrease by. + */ +int volume_dec(lua_State*); + +/** Divides the volume by the given value. + * + * The value to divide by may either be a scalar, that's applied to all channels, + * or another instance of @{Volume}, which would be applied channel by channel. + * + * It is possible to divide a @{Volume} by itself. + * + * This is only valid for software volumes. + * + * @function Volume:divide + * @tparam number|Volume value The volume to divide by. + */ +int volume_divide(lua_State*); + +/** Returns the volume of a single channel. + * + * @function Volume:get + * @tparam number index The channel index + * @treturn number The channel's volume + */ +int volume_get(lua_State*); + +/** Increases the volume by the given amount. + * + * The proportions between the channels are kept. + * + * @function Volume:inc + * @tparam number value the value to increase by. + */ +int volume_inc(lua_State*); + +/** Returns `true` when all channels are muted. + * + * @function Volume:is_muted + * @treturn boolean + */ +int volume_is_muted(lua_State*); + +/** Returns `true` when all channels are on normal level. + * + * @function Volume:is_norm + * @treturn boolean + */ +int volume_is_norm(lua_State*); + +/** Returns the maximum volume out of all channels. + * + * @function Volume:max + * @treturn number + */ +int volume_max(lua_State*); + +/** Returns the minimum volume out of all channels. + * + * @function Volume:min + * @treturn number + */ +int volume_min(lua_State*); + +/** Multiplies the volume by the given amount. + * + * The value to multiply with may either be a scalar, that's applied to all channels, + * or another instance of @{Volume}, which would be applied channel by channel. + * + * It is possible to multiply a @{Volume} by itself. + * + * This is only valid for software volumes. + * + * @function Volume:multiply + * @tparam number|Volume value + */ +int volume_multiply(lua_State*); + +/** Mutes all channels. + * + * @function Volume:mute + */ +int volume_mute(lua_State*); + +/** Resets all channels to normal volume. + * + * @function Volume:reset + */ +int volume_reset(lua_State*); + +/** Scales all channels to the passed amount. + * + * This adjust all channel volumes so that the maximum between them equals the given value, while + * keeping proportions between channels the same. + * + * @function Volume:scale + * @tparam number value The value to scale to. + */ +int volume_scale(lua_State*); + +/** Sets a channel to the given value. + * + * @function Volume:set + * @tparam number index The channel index. + * @tparam number value The volume to set to. + */ +int volume_set(lua_State*); + +/** Sets a number of channels to the given volume value. + * + * @function Volume:set_channels + * @tparam number channels The number of channels to set + * @tparam number value The volume to set to. + */ +int volume_set_channels(lua_State*); + + +static const struct luaL_Reg volume_f[] = { + {"avg", volume_avg }, + { "channels_equal_to", volume_channels_equal_to}, + { "dec", volume_dec }, + { "divide", volume_divide }, + { "get", volume_get }, + { "inc", volume_inc }, + { "is_muted", volume_is_muted }, + { "is_norm", volume_is_norm }, + { "is_valid", volume_is_valid }, + { "max", volume_max }, + { "min", volume_min }, + { "multiply", volume_multiply }, + { "mute", volume_mute }, + { "reset", volume_reset }, + { "scale", volume_scale }, + { "set", volume_set }, + { NULL, NULL } +}; + + +// We don't add `__index` here, as it needs to be handled specially, +// to allow indexing both by channel index as well as accessing the methods above. +static const struct luaL_Reg volume_mt[] = { + {"__len", volume__len }, + { "__tostring", volume__tostring}, + { "__eq", volume__eq }, + { "__newindex", volume__newindex}, + { NULL, NULL } +}; + + +static const struct luaL_Reg volume_lib[] = { + {"is_valid", volume_is_valid}, + { NULL, NULL } +}; + + +#endif // volume_h_INCLUDED + diff --git a/tools/process_docs.sh b/tools/process_docs.sh index 9b5fd46..f6ab73f 100644 --- a/tools/process_docs.sh +++ b/tools/process_docs.sh @@ -14,7 +14,7 @@ run() { "$@" } -find src -iname '*.lua' -or -iname '*.c' -not -path '*/internal/*' | while read -r f; do +find src -iname '*.lua' -or -iname '*.c' -or -iname '*.h' -not -path '*/internal/*' | while read -r f; do mkdir -p "$(dirname "$OUT/$f")" run "$LUA" ./tools/preprocessor.lua "$f" "$OUT/$f" done From 00d95de6d983428fc8bb3c110b12b02f44e541fa Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 15 May 2022 23:11:00 +0200 Subject: [PATCH 06/44] chore: Ignore LuaRocks working files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index db23e87..4ef1917 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ lua.debug .cache/clangd compile_commands.json .sass-cache + +*.rockspec.asc +*.src.rock From 9a780045ffaa35a6f0aa0034e0ceff8ee3626922 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 15 May 2022 23:11:28 +0200 Subject: [PATCH 07/44] doc: Add main usage example --- doc/config.ld | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/config.ld b/doc/config.ld index f3babc2..028a5d3 100644 --- a/doc/config.ld +++ b/doc/config.ld @@ -14,6 +14,28 @@ may either be just a boolean, for operations that don't return data, or the actu All numeric indices (such as sink or source indices) are adjusted to be 1-based in typical Lua fashion. This means that when comparing the output of calls like @{Context:get_sinks} to the output of tools like `pactl`, indices will be off by one. + + local lgi = require("lgi") + local pulseaudio = require("lua_libpulse_glib") + local ppretty = require("pl.pretty") + + local pa = pulseaudio.new() + local ctx = pa:context() + + local loop = lgi.GLib.MainLoop.new() + + ctx:connect(nil, function(state) + if state == 4 then + print("Connection is ready") + + ctx:get_sinks(function(sinks) + ppretty.dump(sinks) + loop:quit() + end) + end + end) + + loop:run() ]] template = true From d3034806400fc866d4743b16ac4968cb856836d2 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 15 May 2022 23:11:50 +0200 Subject: [PATCH 08/44] build: Fix rockspec summary --- rocks/lua-libpulse-glib-scm-1.rockspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocks/lua-libpulse-glib-scm-1.rockspec b/rocks/lua-libpulse-glib-scm-1.rockspec index 5392e06..4c8393e 100644 --- a/rocks/lua-libpulse-glib-scm-1.rockspec +++ b/rocks/lua-libpulse-glib-scm-1.rockspec @@ -6,7 +6,7 @@ source = { } description = { - summary = "An asynchronous high(er)-level API wrapper for LGI", + summary = "Lua bindings for PulseAudio's libpulse, using the GLib Main Loop.", homepage = "https://github.com/sclu1034/lua-libpulse-glib", license = "GPLv3" } From 12dd08f13a1d6bfe3e83f8b22b3966122a0fe0a9 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 15 May 2022 23:12:13 +0200 Subject: [PATCH 09/44] doc: Fix module names --- src/lua_libpulse_glib/context.h | 2 +- src/lua_libpulse_glib/proplist.h | 2 +- src/lua_libpulse_glib/pulseaudio.h | 2 +- src/lua_libpulse_glib/volume.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index a68c071..9888230 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -6,7 +6,7 @@ * In many cases, sinks and sources may be addressed by either their name or their numeric index. * Both can be queried using the `get_(sink|source)_info` or `get_(sink|source)s` calls. * - * @module pulseaudio.context + * @module lua_libpulse_glib.context */ #pragma once diff --git a/src/lua_libpulse_glib/proplist.h b/src/lua_libpulse_glib/proplist.h index bacb3ed..7139589 100644 --- a/src/lua_libpulse_glib/proplist.h +++ b/src/lua_libpulse_glib/proplist.h @@ -10,7 +10,7 @@ * * Additional operations are exposed as methods, as documented below. * - * @module pulseaudio.proplist + * @module lua_libpulse_glib.proplist */ #pragma once diff --git a/src/lua_libpulse_glib/pulseaudio.h b/src/lua_libpulse_glib/pulseaudio.h index e329771..4e9eb60 100644 --- a/src/lua_libpulse_glib/pulseaudio.h +++ b/src/lua_libpulse_glib/pulseaudio.h @@ -1,6 +1,6 @@ /** Bindings for PulseAudio's libpulse, using the GLib Main Loop. * - * @module pulseaudio + * @module lua_libpulse_glib */ #pragma once diff --git a/src/lua_libpulse_glib/volume.h b/src/lua_libpulse_glib/volume.h index 01f8631..f21bb98 100644 --- a/src/lua_libpulse_glib/volume.h +++ b/src/lua_libpulse_glib/volume.h @@ -3,7 +3,7 @@ * Contrary to libpulse, methods that change the a @{Volume} object generally don't return anything, but * instead change the instance itself. * - * @module pulseaudio.volume + * @module lua_libpulse_glib.volume */ #ifndef volume_h_INCLUDED #define volume_h_INCLUDED From 69c2fd7fafb4c790a3476b3cd94d920f5082c17f Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 15 May 2022 23:17:21 +0200 Subject: [PATCH 10/44] doc: Improve quick start documentation --- README.adoc | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/README.adoc b/README.adoc index 10ac33a..60f209e 100644 --- a/README.adoc +++ b/README.adoc @@ -31,15 +31,37 @@ image:{url-luarocks-badge}[LuaRocks Package, link={url-luarocks-link}] https://freedesktop.org/software/pulseaudio/doxygen/index.html[libpulse] bindings for use with a GLib MainLoop via https://github.com/lgi-devs/lgi/[LGI]. -== Installation +== Quick Start -_lua-libpulse-glib_ is available via LuaRocks: +Install https://github.com/lgi-devs/lgi[lgi] and _lua_libpulse_glib_ from LuaRocks: [source,shell] ---- +luarocks install lgi luarocks install lua-libpulse-glib ---- -When cloning/vendoring the library, the following dependencies are required: +[source,lua] +---- +local lgi = require("lgi") +local pulseaudio = require("lua_libpulse_glib") +local ppretty = require("pl.pretty") -* https://github.com/lgi-devs/lgi[lgi] +local pa = pulseaudio.new() +local ctx = pa:context() + +local loop = lgi.GLib.MainLoop.new() + +ctx:connect(nil, function(state) + if state == 4 then + print("Connection is ready") + + ctx:get_sinks(function(sinks) + ppretty.dump(sinks) + loop:quit() + end) + end +end) + +loop:run() +--- From 533f9a563dd72ef63e809a10a4c89616327228bb Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 15 May 2022 23:17:36 +0200 Subject: [PATCH 11/44] build: Remove unused dependencies --- rocks/lua-libpulse-glib-scm-1.rockspec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rocks/lua-libpulse-glib-scm-1.rockspec b/rocks/lua-libpulse-glib-scm-1.rockspec index 4c8393e..257547d 100644 --- a/rocks/lua-libpulse-glib-scm-1.rockspec +++ b/rocks/lua-libpulse-glib-scm-1.rockspec @@ -12,9 +12,7 @@ description = { } dependencies = { - "lua >= 5.1", - "lgi", - "async.lua" + "lua >= 5.1" } build = { From 65483ec8a5b7cdc3009c8146b49980e8d2103751 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 16 May 2022 13:45:19 +0200 Subject: [PATCH 12/44] doc: Fix code block --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 60f209e..68610bb 100644 --- a/README.adoc +++ b/README.adoc @@ -64,4 +64,4 @@ ctx:connect(nil, function(state) end) loop:run() ---- +---- From 4e1b02e65fe108acf5d1d1e2f1a2dd71ec500214 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 16 May 2022 13:53:20 +0200 Subject: [PATCH 13/44] feat(context): Implement default sink and source setters --- src/lua_libpulse_glib/context.h | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index 9888230..bda7840 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -61,7 +61,27 @@ int context_connect(lua_State*); * * @function Context:disconnect */ -int context_disconnect(lua_State* L); +int context_disconnect(lua_State*); + +/** Sets the default sink. + * + * @function Context:set_default_sink + * @async + * @tparam string sink Name of the sink to set as default. + * @treturn[opt] string error + * @treturn boolean + */ +int context_set_default_sink(lua_State*); + +/** Sets the default source. + * + * @function Context:set_default_source + * @async + * @tparam string source Name of the source to set as default. + * @treturn[opt] string error + * @treturn boolean + */ +int context_set_default_source(lua_State*); /** Gets information about the server the context is connected to. @@ -432,6 +452,8 @@ static const struct luaL_Reg context_mt[] = { static const struct luaL_Reg context_f[] = { {"connect", context_connect }, { "disconnect", context_disconnect }, + { "set_default_sink", context_set_default_sink }, + { "set_default_source", context_set_default_source }, { "get_server_info", context_get_server_info }, { "get_sinks", context_get_sink_info_list }, { "get_sink_info", context_get_sink_info }, From d88abd87c628d81fd691b4843ebea160a90d9344 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 16 May 2022 14:22:56 +0200 Subject: [PATCH 14/44] feat(context): Add getter for connection state --- src/lua_libpulse_glib/context.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index bda7840..f79cb80 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -63,6 +63,14 @@ int context_connect(lua_State*); */ int context_disconnect(lua_State*); +/** Returns the current connection state. + * + * @function Context:get_state + * @treturn number + */ +int context_get_state(lua_State*); + + /** Sets the default sink. * * @function Context:set_default_sink @@ -452,6 +460,7 @@ static const struct luaL_Reg context_mt[] = { static const struct luaL_Reg context_f[] = { {"connect", context_connect }, { "disconnect", context_disconnect }, + { "get_state", context_get_state }, { "set_default_sink", context_set_default_sink }, { "set_default_source", context_set_default_source }, { "get_server_info", context_get_server_info }, From bfc322c3adfcab45cf03353f3ba8d5b208a51df5 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 16 May 2022 15:59:26 +0200 Subject: [PATCH 15/44] feat(context): Implement event subscriptions --- src/lua_libpulse_glib/context.c | 106 +++++++++++++++++++++++++++++++- src/lua_libpulse_glib/context.h | 3 + 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/lua_libpulse_glib/context.c b/src/lua_libpulse_glib/context.c index 324a48f..ca28636 100644 --- a/src/lua_libpulse_glib/context.c +++ b/src/lua_libpulse_glib/context.c @@ -1,13 +1,13 @@ #include "context.h" -#include "callback.h" #include "pulseaudio.h" #include #include +#include -/* Calls the user-provided callback with the updates state info. +/* Calls the user-provided callback with the updated state info. */ void context_state_callback(pa_context* c, void* userdata) { context_state_callback_data* data = (context_state_callback_data*) userdata; @@ -26,6 +26,27 @@ void context_state_callback(pa_context* c, void* userdata) { } +/* Calls the user-prodivded event callbacks. + */ +void context_event_callback(pa_context* c, pa_subscription_event_type_t event_type, uint32_t index, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; + lua_State* L = data->L; + + luaL_checktype(L, 1, LUA_TFUNCTION); + luaL_checkudata(L, 2, LUA_PA_CONTEXT); + + // `lua_call` will pop the function and arguments from the stack, but this callback will likely be called + // multiple times. + // To preseve the values for future calls, we need to duplicate them. + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_pushinteger(L, event_type); + lua_pushinteger(L, index); + + lua_call(L, 3, 0); +} + + int context_new(lua_State* L, pa_mainloop_api* pa_api) { const char* name = luaL_checkstring(L, -1); // TODO: libpulse recommends using `new_with_proplist` instead. But I need to figure out that `proplist` first. @@ -41,6 +62,7 @@ int context_new(lua_State* L, pa_mainloop_api* pa_api) { lgi_ctx->context = ctx; lgi_ctx->connected = FALSE; lgi_ctx->state_callback_data = (context_state_callback_data*) calloc(1, sizeof(struct context_state_callback_data)); + lgi_ctx->event_callback_data = prepare_lua_callback(L); luaL_getmetatable(L, LUA_PA_CONTEXT); lua_setmetatable(L, -2); @@ -67,6 +89,10 @@ int context__gc(lua_State* L) { free(ctx->state_callback_data); } + if (ctx->event_callback_data != NULL) { + free_lua_callback(ctx->event_callback_data); + } + pa_context_unref(ctx->context); return 0; } @@ -117,6 +143,7 @@ int context_connect(lua_State* L) { ctx->state_callback_data = data; pa_context_set_state_callback(ctx->context, context_state_callback, data); + pa_context_set_subscribe_callback(ctx->context, context_event_callback, ctx->event_callback_data); // TODO: Check if I need to create bindings for `pa_spawn_api`. int ret = pa_context_connect(ctx->context, server, flags, NULL); @@ -179,3 +206,78 @@ int context_set_default_source(lua_State* L) { return 0; } + + +int context_subscribe(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + luaL_checktype(L, 2, LUA_TFUNCTION); + + size_t pos = lua_objlen(ctx->event_callback_data->L, 1) + 1; + // Duplicate the callback function, so we can move it over to the other thread + lua_pushvalue(L, 2); + lua_xmove(L, ctx->event_callback_data->L, 1); + lua_rawseti(ctx->event_callback_data->L, 1, pos); + + lua_pushinteger(L, pos); + return 1; +} + + +int context_unsubscribe(lua_State* L) { + lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_State* thread_L = ctx->event_callback_data->L; + size_t pos = 0; + size_t len = lua_objlen(thread_L, 1); + + if (len == 0) { + return 0; + } + + switch (lua_type(L, 2)) { + case LUA_TNUMBER: { + pos = lua_tointeger(L, 2); + break; + } + case LUA_TFUNCTION: { + bool found = false; + size_t i = 0; + + // Duplicate the function value, so we can move it other to the other thread for comparing + lua_pushvalue(L, -1); + lua_xmove(L, thread_L, 1); + int fn_index = lua_gettop(thread_L); + + lua_pushnil(L); + while (lua_next(thread_L, 1) != 0) { + ++i; + + if (lua_equal(thread_L, -1, fn_index) == 1) { + pos = i; + lua_pop(thread_L, 2); + break; + } + + // Remove the value, but keep the key to continue iterating + lua_pop(thread_L, 1); + } + + if (!found) { + return luaL_error(L, "couldn't find this function in the list of subscriptions"); + } + + break; + } + default: { + return luaL_argerror(L, 2, "expected number or function"); + } + } + + for (; pos < len; ++pos) { + lua_rawgeti(thread_L, 1, pos + 1); + lua_rawseti(thread_L, 1, pos); + } + lua_pushnil(thread_L); + lua_rawseti(thread_L, 1, len); + + return 0; +} diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index f79cb80..9c497c1 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -10,6 +10,8 @@ */ #pragma once +#include "callback.h" + #include #include #include @@ -29,6 +31,7 @@ typedef struct lua_pa_context { pa_context* context; bool connected; context_state_callback_data* state_callback_data; + simple_callback_data* event_callback_data; } lua_pa_context; From eed57afbda7d6b9893a2cdc8999439322f7b2b47 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 16 May 2022 16:24:36 +0200 Subject: [PATCH 16/44] feat(context): Simplify callbacks The same simple callback structure works for all the callbacks I've built so far. --- src/lua_libpulse_glib/context.c | 32 ++++---------------------------- src/lua_libpulse_glib/context.h | 8 +------- 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/src/lua_libpulse_glib/context.c b/src/lua_libpulse_glib/context.c index ca28636..a1631c2 100644 --- a/src/lua_libpulse_glib/context.c +++ b/src/lua_libpulse_glib/context.c @@ -10,7 +10,7 @@ /* Calls the user-provided callback with the updated state info. */ void context_state_callback(pa_context* c, void* userdata) { - context_state_callback_data* data = (context_state_callback_data*) userdata; + simple_callback_data* data = (simple_callback_data*) userdata; luaL_checktype(data->L, 1, LUA_TFUNCTION); luaL_checkudata(data->L, 2, LUA_PA_CONTEXT); // `lua_call` will pop the function and arguments from the stack, but this callback will likely be called @@ -61,7 +61,7 @@ int context_new(lua_State* L, pa_mainloop_api* pa_api) { } lgi_ctx->context = ctx; lgi_ctx->connected = FALSE; - lgi_ctx->state_callback_data = (context_state_callback_data*) calloc(1, sizeof(struct context_state_callback_data)); + lgi_ctx->state_callback_data = prepare_lua_callback(L); lgi_ctx->event_callback_data = prepare_lua_callback(L); luaL_getmetatable(L, LUA_PA_CONTEXT); @@ -80,13 +80,7 @@ int context__gc(lua_State* L) { } if (ctx->state_callback_data != NULL) { - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - luaL_unref(L, -1, ctx->state_callback_data->thread_ref); - free(ctx->state_callback_data); + free_lua_callback(ctx->state_callback_data); } if (ctx->event_callback_data != NULL) { @@ -124,25 +118,7 @@ int context_connect(lua_State* L) { if (nargs > 3) flags = luaL_checkinteger(L, 4); - // Prepare a new thread to run the callback with - lua_pushstring(L, LUA_PULSEAUDIO); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushstring(L, LUA_PA_REGISTRY); - lua_gettable(L, -2); - lua_State* thread = lua_newthread(L); - int thread_ref = luaL_ref(L, -2); - - // Copy the callback function and arguments to the thread's stack - lua_pushvalue(L, 3); - lua_pushvalue(L, 1); - lua_xmove(L, thread, 2); - - context_state_callback_data* data = calloc(1, sizeof(struct context_state_callback_data)); - data->L = thread; - data->thread_ref = thread_ref; - ctx->state_callback_data = data; - - pa_context_set_state_callback(ctx->context, context_state_callback, data); + pa_context_set_state_callback(ctx->context, context_state_callback, ctx->state_callback_data); pa_context_set_subscribe_callback(ctx->context, context_event_callback, ctx->event_callback_data); // TODO: Check if I need to create bindings for `pa_spawn_api`. diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index 9c497c1..6524e56 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -21,16 +21,10 @@ #define LUA_PA_CONTEXT "pulseaudio.context" -typedef struct context_state_callback_data { - lua_State* L; - int thread_ref; -} context_state_callback_data; - - typedef struct lua_pa_context { pa_context* context; bool connected; - context_state_callback_data* state_callback_data; + simple_callback_data* state_callback_data; simple_callback_data* event_callback_data; } lua_pa_context; From 5634e205a21ad202444ea3632533da08b3ae802a Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 16 May 2022 16:41:40 +0200 Subject: [PATCH 17/44] fix(context): Fix missing methods Some methods weren't actually registered in the class' metatable. --- src/lua_libpulse_glib/context.h | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index 6524e56..dacd077 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -32,6 +32,27 @@ typedef struct lua_pa_context { int context_new(lua_State*, pa_mainloop_api*); int context__gc(lua_State*); +/// Callback Functions +/// @section callbacks + +/** The callback signature for @{Context:subscribe}. + * + * See [here](https://freedesktop.org/software/pulseaudio/doxygen/subscribe.html) how to use the `event_type` + * parameter to determine the event that triggered the callback. + * + * @function event_callback + * @tparam Context context The context that the callback is subscribed to. + * @tparam number event_type A bitflag-ish value from libpulse that represents the event that caused the callback. + * @tparam number index + */ + +/** The callback signature for @{Context:connect}. + * + * @function state_callback + * @tparam Context context The context that the callback is subscribed to. + * @tparam number state An enum that represents the current connection state. + */ + /// Context /// @type Context @@ -67,6 +88,28 @@ int context_disconnect(lua_State*); */ int context_get_state(lua_State*); +/** Registers a callback function as event handler. + * + * This callback will be called whenever the server sends a suitable event. + * + * Any number of callbacks may be registered at the same time, and can be unscubscribed with + * @{Context:unsubscribe}, using the returned subscription ID. + * + * @function Context:subscribe + * @tparam function cb + * @treturn number The subscription ID. + */ +int context_subscribe(lua_State*); + +/** Removes an event handler subscription. + * + * Subscriptions may be removed either by their ID or by their callback function. + * + * @function Context:unsubscribe + * @tparam number|function handler The handler to remove. + */ +int context_unsubscribe(lua_State*); + /** Sets the default sink. * @@ -457,6 +500,8 @@ static const struct luaL_Reg context_mt[] = { static const struct luaL_Reg context_f[] = { {"connect", context_connect }, { "disconnect", context_disconnect }, + { "subscribe", context_subscribe }, + { "unsubscribe", context_unsubscribe }, { "get_state", context_get_state }, { "set_default_sink", context_set_default_sink }, { "set_default_source", context_set_default_source }, From 188c8a7666ed2b81e5814c1fd41c47eb55cd0bf5 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Fri, 20 May 2022 19:24:50 +0200 Subject: [PATCH 18/44] doc: Fix missing function parameter in example --- README.adoc | 2 +- doc/config.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 68610bb..69dbf9a 100644 --- a/README.adoc +++ b/README.adoc @@ -48,7 +48,7 @@ local pulseaudio = require("lua_libpulse_glib") local ppretty = require("pl.pretty") local pa = pulseaudio.new() -local ctx = pa:context() +local ctx = pa:context("My Test App") local loop = lgi.GLib.MainLoop.new() diff --git a/doc/config.ld b/doc/config.ld index 028a5d3..cdfeb49 100644 --- a/doc/config.ld +++ b/doc/config.ld @@ -20,7 +20,7 @@ indices will be off by one. local ppretty = require("pl.pretty") local pa = pulseaudio.new() - local ctx = pa:context() + local ctx = pa:context("My Test App") local loop = lgi.GLib.MainLoop.new() From e0aaa99cb18c3e5fa9160ce0787c002615bd0492 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 23 May 2022 14:52:55 +0200 Subject: [PATCH 19/44] fix(context): Fix callback functions The stack setup for callback threads was all over the place, and pretty messed up. --- src/lua_libpulse_glib/callback.c | 14 ++++-- src/lua_libpulse_glib/callback.h | 9 ++-- src/lua_libpulse_glib/context.c | 20 +++++--- src/lua_libpulse_glib/introspection.c | 66 +++++++++++++-------------- src/lua_libpulse_glib/lua_util.h | 1 + 5 files changed, 64 insertions(+), 46 deletions(-) diff --git a/src/lua_libpulse_glib/callback.c b/src/lua_libpulse_glib/callback.c index 25eef27..108a1d8 100644 --- a/src/lua_libpulse_glib/callback.c +++ b/src/lua_libpulse_glib/callback.c @@ -3,7 +3,7 @@ #include "pulseaudio.h" -simple_callback_data* prepare_lua_callback(lua_State* L) { +simple_callback_data* prepare_lua_callback(lua_State* L, int callback_index) { // Prepare a new thread to run the callback with lua_pushstring(L, LUA_PULSEAUDIO); lua_rawget(L, LUA_REGISTRYINDEX); @@ -12,15 +12,21 @@ simple_callback_data* prepare_lua_callback(lua_State* L) { lua_State* thread = lua_newthread(L); int thread_ref = luaL_ref(L, -2); - // Copy the callback function to the thread's stack - lua_pushvalue(L, 2); - lua_xmove(L, thread, 1); + if (callback_index != 0) { + // Copy the callback function to the thread's stack + luaL_checktype(L, callback_index, LUA_TFUNCTION); + lua_pushvalue(L, callback_index); + lua_xmove(L, thread, 1); + } simple_callback_data* data = malloc(sizeof(struct simple_callback_data)); data->L = thread; data->thread_ref = thread_ref; data->is_list = false; + // Clean up the intermediate data from creating the thread + lua_pop(L, 2); + return data; } diff --git a/src/lua_libpulse_glib/callback.h b/src/lua_libpulse_glib/callback.h index be9aa49..97ced0f 100644 --- a/src/lua_libpulse_glib/callback.h +++ b/src/lua_libpulse_glib/callback.h @@ -27,16 +27,19 @@ typedef struct simple_callback_data { // // The returned callback data needs to be `free()`d at the end of the callback. `free_lua_callback` // handles both `free()` and `luaL_unref()`. -simple_callback_data* prepare_lua_callback(lua_State* L); +// +// The first `int` is the index to a function on the stack. If this is non-zero, that value will +// be copied to the thread's stack. +simple_callback_data* prepare_lua_callback(lua_State*, int); // Removes the thread reference, to allow the thread to be garbage collected, and `free`s // the callback data. -void free_lua_callback(simple_callback_data* data); +void free_lua_callback(simple_callback_data*); // Simple implementation of `pa_context_success_cb_t` that calls a provided Lua function. -void success_callback(pa_context* c, int success, void* userdata); +void success_callback(pa_context*, int, void*); #endif // callback_h_INCLUDED diff --git a/src/lua_libpulse_glib/context.c b/src/lua_libpulse_glib/context.c index a1631c2..34eba5d 100644 --- a/src/lua_libpulse_glib/context.c +++ b/src/lua_libpulse_glib/context.c @@ -12,12 +12,12 @@ void context_state_callback(pa_context* c, void* userdata) { simple_callback_data* data = (simple_callback_data*) userdata; luaL_checktype(data->L, 1, LUA_TFUNCTION); - luaL_checkudata(data->L, 2, LUA_PA_CONTEXT); // `lua_call` will pop the function and arguments from the stack, but this callback will likely be called // multiple times. // To preseve the values for future calls, we need to duplicate them. lua_pushvalue(data->L, 1); - lua_pushvalue(data->L, 2); + // This can't really fail, but for consistency, we keep the error value. + lua_pushnil(data->L); pa_context_state_t state = pa_context_get_state(c); lua_pushinteger(data->L, state); @@ -61,8 +61,11 @@ int context_new(lua_State* L, pa_mainloop_api* pa_api) { } lgi_ctx->context = ctx; lgi_ctx->connected = FALSE; - lgi_ctx->state_callback_data = prepare_lua_callback(L); - lgi_ctx->event_callback_data = prepare_lua_callback(L); + lgi_ctx->state_callback_data = prepare_lua_callback(L, 0); + lgi_ctx->event_callback_data = prepare_lua_callback(L, 0); + + // Create the table used to store the subscription callbacks. + lua_newtable(lgi_ctx->event_callback_data->L); luaL_getmetatable(L, LUA_PA_CONTEXT); lua_setmetatable(L, -2); @@ -118,6 +121,11 @@ int context_connect(lua_State* L) { if (nargs > 3) flags = luaL_checkinteger(L, 4); + // Make sure the callback function is at a known position in the thread's stack + lua_settop(ctx->state_callback_data->L, 0); + lua_pushvalue(L, 3); + lua_xmove(L, ctx->state_callback_data->L, 1); + pa_context_set_state_callback(ctx->context, context_state_callback, ctx->state_callback_data); pa_context_set_subscribe_callback(ctx->context, context_event_callback, ctx->event_callback_data); @@ -150,7 +158,7 @@ int context_set_default_sink(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); const char* name = luaL_checkstring(L, 2); - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_set_default_sink(ctx->context, name, success_callback, data); if (op == NULL) { @@ -169,7 +177,7 @@ int context_set_default_source(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); const char* name = luaL_checkstring(L, 2); - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_set_default_source(ctx->context, name, success_callback, data); if (op == NULL) { diff --git a/src/lua_libpulse_glib/introspection.c b/src/lua_libpulse_glib/introspection.c index 3ac4b9e..33d13f6 100644 --- a/src/lua_libpulse_glib/introspection.c +++ b/src/lua_libpulse_glib/introspection.c @@ -34,7 +34,7 @@ int context_get_server_info(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 2); pa_operation* op = pa_context_get_server_info(ctx->context, server_info_callback, data); if (op == NULL) { @@ -94,7 +94,7 @@ int context_get_sink_info_list(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 2); data->is_list = true; // Create the list to store infos in lua_newtable(data->L); @@ -123,7 +123,7 @@ int context_get_sink_info_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 2); pa_operation* op = pa_context_get_sink_info_by_name(ctx->context, name, sink_info_callback, data); if (op == NULL) { @@ -152,7 +152,7 @@ int context_get_sink_info_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_get_sink_info_by_index(ctx->context, (uint32_t) index - 1, sink_info_callback, data); if (op == NULL) { @@ -193,7 +193,7 @@ int context_set_sink_volume_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); const char* name = luaL_checkstring(L, 2); pa_cvolume* volume = volume_from_lua(L, 3); @@ -228,7 +228,7 @@ int context_set_sink_volume_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_cvolume* volume = volume_from_lua(L, 3); pa_operation* op = @@ -277,7 +277,7 @@ int context_set_sink_mute_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_sink_mute_by_name(ctx->context, name, mute, success_callback, data); if (op == NULL) { @@ -307,7 +307,7 @@ int context_set_sink_mute_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_sink_mute_by_index(ctx->context, (uint32_t) index - 1, mute, success_callback, data); @@ -351,7 +351,7 @@ int context_set_sink_suspended_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_suspend_sink_by_name(ctx->context, name, suspended, success_callback, data); if (op == NULL) { @@ -381,7 +381,7 @@ int context_set_sink_suspended_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_suspend_sink_by_index(ctx->context, (uint32_t) index - 1, suspended, success_callback, data); @@ -467,7 +467,7 @@ int context_get_source_info_list(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 2); data->is_list = true; // Create the list to store infos in lua_newtable(data->L); @@ -496,7 +496,7 @@ int context_get_source_info_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_get_source_info_by_name(ctx->context, name, source_info_callback, data); if (op == NULL) { @@ -525,7 +525,7 @@ int context_get_source_info_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_get_source_info_by_index(ctx->context, (uint32_t) index - 1, source_info_callback, data); @@ -567,7 +567,7 @@ int context_set_source_volume_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); const char* name = luaL_checkstring(L, 2); pa_cvolume* volume = volume_from_lua(L, 3); @@ -602,7 +602,7 @@ int context_set_source_volume_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_cvolume* volume = volume_from_lua(L, 3); pa_operation* op = @@ -651,7 +651,7 @@ int context_set_source_mute_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_source_mute_by_name(ctx->context, name, mute, success_callback, data); if (op == NULL) { @@ -681,7 +681,7 @@ int context_set_source_mute_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_source_mute_by_index(ctx->context, (uint32_t) index - 1, mute, success_callback, data); @@ -725,7 +725,7 @@ int context_set_source_suspended_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_suspend_source_by_name(ctx->context, name, suspended, success_callback, data); if (op == NULL) { @@ -755,7 +755,7 @@ int context_set_source_suspended_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_suspend_source_by_index(ctx->context, (uint32_t) index - 1, suspended, success_callback, data); @@ -832,7 +832,7 @@ int context_get_sink_input_info_list(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 2); data->is_list = true; // Create the list to store infos in lua_newtable(data->L); @@ -864,7 +864,7 @@ int context_get_sink_input_info(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_get_sink_input_info(ctx->context, (uint32_t) index - 1, sink_input_info_callback, data); @@ -915,7 +915,7 @@ int context_move_sink_input_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_move_sink_input_by_index(ctx->context, (uint32_t) sink_input_index - 1, @@ -954,7 +954,7 @@ int context_move_sink_input_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_move_sink_input_by_name(ctx->context, (uint32_t) sink_input_index - 1, @@ -985,7 +985,7 @@ int context_set_sink_input_volume(lua_State* L) { } pa_cvolume* volume = volume_from_lua(L, 3); - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_sink_input_volume(ctx->context, (uint32_t) index - 1, volume, success_callback, data); @@ -1009,7 +1009,7 @@ int context_set_sink_input_mute(lua_State* L) { } bool mute = lua_toboolean(L, 3); - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_sink_input_mute(ctx->context, (uint32_t) index - 1, mute, success_callback, data); if (op == NULL) { @@ -1032,7 +1032,7 @@ int context_kill_sink_input(lua_State* L) { } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_kill_sink_input(ctx->context, (uint32_t) index - 1, success_callback, data); if (op == NULL) { @@ -1092,7 +1092,7 @@ int context_get_source_output_info_list(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 2); data->is_list = true; // Create the list to store infos in lua_newtable(data->L); @@ -1124,7 +1124,7 @@ int context_get_source_output_info(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_get_source_output_info(ctx->context, (uint32_t) index - 1, source_output_info_callback, data); @@ -1175,7 +1175,7 @@ int context_move_source_output_by_index(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_move_source_output_by_index(ctx->context, (uint32_t) source_output_index - 1, @@ -1214,7 +1214,7 @@ int context_move_source_output_by_name(lua_State* L) { return 0; } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_move_source_output_by_name(ctx->context, (uint32_t) source_output_index - 1, @@ -1245,7 +1245,7 @@ int context_set_source_output_volume(lua_State* L) { } pa_cvolume* volume = volume_from_lua(L, 3); - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_source_output_volume(ctx->context, (uint32_t) index - 1, volume, success_callback, data); @@ -1269,7 +1269,7 @@ int context_set_source_output_mute(lua_State* L) { } bool mute = lua_toboolean(L, 3); - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 4); pa_operation* op = pa_context_set_source_output_mute(ctx->context, (uint32_t) index - 1, mute, success_callback, data); @@ -1293,7 +1293,7 @@ int context_kill_source_output(lua_State* L) { } - simple_callback_data* data = prepare_lua_callback(L); + simple_callback_data* data = prepare_lua_callback(L, 3); pa_operation* op = pa_context_kill_source_output(ctx->context, (uint32_t) index - 1, success_callback, data); if (op == NULL) { diff --git a/src/lua_libpulse_glib/lua_util.h b/src/lua_libpulse_glib/lua_util.h index 9f7a903..139d8cd 100644 --- a/src/lua_libpulse_glib/lua_util.h +++ b/src/lua_libpulse_glib/lua_util.h @@ -12,4 +12,5 @@ typedef struct luaU_enumfield { const char* value; } luaU_enumfield; + #endif // lua_util_h_INCLUDED From 6eb79d4d8df6c227e0bc75ea3d15a264f99cb365 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 23 May 2022 15:38:57 +0200 Subject: [PATCH 20/44] fix(volume): Fix hard coded stack index --- src/lua_libpulse_glib/volume.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_libpulse_glib/volume.c b/src/lua_libpulse_glib/volume.c index 73c3466..f2e514a 100644 --- a/src/lua_libpulse_glib/volume.c +++ b/src/lua_libpulse_glib/volume.c @@ -27,7 +27,7 @@ int volume_to_lua(lua_State* L, const pa_cvolume* pa_volume) { // by GC. Makes this easier to use. But only do so after the current version has been committed // once, just so it stays available. pa_cvolume* volume_from_lua(lua_State* L, int index) { - switch (lua_type(L, 2)) { + switch (lua_type(L, index)) { case LUA_TTABLE: { uint8_t channels = (uint8_t) lua_objlen(L, index); if (channels > PA_CHANNELS_MAX) { From 0203cbce4c71013ff8c73f741ae7fc2bfb8c7173 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 23 May 2022 15:42:24 +0200 Subject: [PATCH 21/44] fix: Fix library names --- src/lua_libpulse_glib/proplist.h | 2 +- src/lua_libpulse_glib/pulseaudio.c | 1 - src/lua_libpulse_glib/pulseaudio.h | 4 ++-- src/lua_libpulse_glib/volume.h | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lua_libpulse_glib/proplist.h b/src/lua_libpulse_glib/proplist.h index 7139589..15d2d31 100644 --- a/src/lua_libpulse_glib/proplist.h +++ b/src/lua_libpulse_glib/proplist.h @@ -21,7 +21,7 @@ #include #include -#define LUA_PA_PROPLIST "pulseaudio.proplist" +#define LUA_PA_PROPLIST "lua_libpulse_glib.proplist" typedef struct proplist { diff --git a/src/lua_libpulse_glib/pulseaudio.c b/src/lua_libpulse_glib/pulseaudio.c index 666305b..f4b9ea1 100644 --- a/src/lua_libpulse_glib/pulseaudio.c +++ b/src/lua_libpulse_glib/pulseaudio.c @@ -10,7 +10,6 @@ #include #include -#define LUA_PULSEAUDIO "pulseaudio" #if LUA_VERSION_NUM <= 501 // Shamelessly copied from Lua 5.3 source. diff --git a/src/lua_libpulse_glib/pulseaudio.h b/src/lua_libpulse_glib/pulseaudio.h index 4e9eb60..5e0e5a2 100644 --- a/src/lua_libpulse_glib/pulseaudio.h +++ b/src/lua_libpulse_glib/pulseaudio.h @@ -9,8 +9,8 @@ #include -#define LUA_PULSEAUDIO "pulseaudio" -#define LUA_PA_REGISTRY "pulseaudio.registry" +#define LUA_PULSEAUDIO "lua_libpulse_glib" +#define LUA_PA_REGISTRY "lua_libpulse_glib.registry" typedef struct pulseaudio { diff --git a/src/lua_libpulse_glib/volume.h b/src/lua_libpulse_glib/volume.h index f21bb98..d931bdc 100644 --- a/src/lua_libpulse_glib/volume.h +++ b/src/lua_libpulse_glib/volume.h @@ -12,7 +12,7 @@ #include #include -#define LUA_PA_VOLUME "pulseaudio.volume" +#define LUA_PA_VOLUME "lua_libpulse_glib.volume" typedef struct volume_t { From b1b8988e7e216a5d6838fc81baa7dc0e88fa57a1 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 23 May 2022 16:27:10 +0200 Subject: [PATCH 22/44] fix(volume): Fix volume library This also makes it possible to load it independently. --- src/lua_libpulse_glib/pulseaudio.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lua_libpulse_glib/pulseaudio.c b/src/lua_libpulse_glib/pulseaudio.c index f4b9ea1..6d6f266 100644 --- a/src/lua_libpulse_glib/pulseaudio.c +++ b/src/lua_libpulse_glib/pulseaudio.c @@ -167,9 +167,27 @@ LUA_MOD_EXPORT int luaopen_lua_libpulse_glib(lua_State* L) { lua_settable(L, -3); lua_rawset(L, LUA_REGISTRYINDEX); - createlib_volume(L); createlib_context(L); createlib_proplist(L); createlib_pulseaudio(L); return 1; } + + +LUA_MOD_EXPORT int luaopen_lua_libpulse_glib_volume(lua_State* L) { + luaL_newmetatable(L, LUA_PA_VOLUME); + + lua_createtable(L, 0, sizeof volume_f / sizeof volume_f[0]); + luaL_setfuncs(L, volume_f, 0); + lua_setfield(L, -2, "__index"); + + luaL_setfuncs(L, volume_mt, 0); + +#if LUA_VERSION_NUM <= 501 + luaL_register(L, LUA_PA_VOLUME, volume_lib); +#else + luaL_newlib(L, volume_lib); +#endif + return 1; +} + From 3ad2c27ff8a10041c50e333f83e0454dfd16897e Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 23 May 2022 16:28:06 +0200 Subject: [PATCH 23/44] feat(volume): Add constructor --- src/lua_libpulse_glib/volume.c | 6 ++++++ src/lua_libpulse_glib/volume.h | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lua_libpulse_glib/volume.c b/src/lua_libpulse_glib/volume.c index f2e514a..8421280 100644 --- a/src/lua_libpulse_glib/volume.c +++ b/src/lua_libpulse_glib/volume.c @@ -6,6 +6,12 @@ #include +int volume_new(lua_State* L) { + pa_cvolume* cvol = volume_from_lua(L, 1); + return volume_to_lua(L, cvol); +} + + int volume_to_lua(lua_State* L, const pa_cvolume* pa_volume) { volume_t* volume = lua_newuserdata(L, sizeof(volume_t)); if (pa_volume == NULL) { diff --git a/src/lua_libpulse_glib/volume.h b/src/lua_libpulse_glib/volume.h index d931bdc..e529143 100644 --- a/src/lua_libpulse_glib/volume.h +++ b/src/lua_libpulse_glib/volume.h @@ -47,6 +47,13 @@ int volume__newindex(lua_State*); /// Static Functions /// @section static +/** Creates an instance of @{Volume}. + * + * @tparam table values An array of channel volumes. + * @treturn Volume + */ +int volume_new(lua_State*); + /** Checks whether a value is a valid @{Volume}. * @@ -228,8 +235,9 @@ static const struct luaL_Reg volume_mt[] = { static const struct luaL_Reg volume_lib[] = { - {"is_valid", volume_is_valid}, - { NULL, NULL } + {"new", volume_new }, + { "is_valid", volume_is_valid}, + { NULL, NULL } }; From 9e9ac22e82d553208e5a3e835ec4901089cbea6b Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 23 May 2022 16:32:04 +0200 Subject: [PATCH 24/44] fix(context): Fix setting volume The volume object needs to be kept in memory until the operation has finished. --- src/lua_libpulse_glib/callback.c | 7 +- src/lua_libpulse_glib/introspection.c | 124 +++++++++++++++++++------- 2 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/lua_libpulse_glib/callback.c b/src/lua_libpulse_glib/callback.c index 108a1d8..24a726a 100644 --- a/src/lua_libpulse_glib/callback.c +++ b/src/lua_libpulse_glib/callback.c @@ -44,11 +44,16 @@ void free_lua_callback(simple_callback_data* data) { free(data); } - +// When preparing a thread for this callback, the function must be at index `1`. +// Values on the stack after that will be ignored. This allows adding userdata and other values +// for the purpose of memory management, to keep them alive until the callback has been called. void success_callback(pa_context* c, int success, void* userdata) { simple_callback_data* data = (simple_callback_data*) userdata; lua_State* L = data->L; + // Copy the callback function to a position from where it can be called. + // There may be other values on the stack for memory management. + lua_pushvalue(L, 1); lua_pushnil(L); lua_pushboolean(L, success); lua_call(L, 2, 0); diff --git a/src/lua_libpulse_glib/introspection.c b/src/lua_libpulse_glib/introspection.c index 33d13f6..d404dd9 100644 --- a/src/lua_libpulse_glib/introspection.c +++ b/src/lua_libpulse_glib/introspection.c @@ -195,9 +195,23 @@ int context_set_sink_volume_by_name(lua_State* L) { simple_callback_data* data = prepare_lua_callback(L, 4); const char* name = luaL_checkstring(L, 2); - pa_cvolume* volume = volume_from_lua(L, 3); - pa_operation* op = pa_context_set_sink_volume_by_name(ctx->context, name, volume, success_callback, data); + if (lua_istable(L, 3)) { + pa_cvolume* volume = volume_from_lua(L, 3); + volume_to_lua(L, volume); + pa_xfree((void*) volume); + } else { + lua_pushvalue(L, 3); + } + + volume_t* vol = luaL_checkudata(L, -1, LUA_PA_VOLUME); + + // Move the volume userdata to the callback's thread. It needs to be kept alive + // until the callback has run. + lua_xmove(L, data->L, 1); + + pa_operation* op = pa_context_set_sink_volume_by_name(ctx->context, name, &vol->inner, success_callback, data); + if (op == NULL) { int error = pa_context_errno(ctx->context); lua_pushvalue(L, 2); @@ -205,17 +219,13 @@ int context_set_sink_volume_by_name(lua_State* L) { lua_call(L, 1, 0); } - // TODO: Is this too early? - // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. - // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. - pa_xfree((void*) volume); - return 0; } int context_set_sink_volume_by_index(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); + lua_Integer index = luaL_checkinteger(L, 2); if (index < 1) { return luaL_error(L, "Sink index out of bounds. Got %d", index); @@ -229,10 +239,23 @@ int context_set_sink_volume_by_index(lua_State* L) { } simple_callback_data* data = prepare_lua_callback(L, 4); - pa_cvolume* volume = volume_from_lua(L, 3); + + if (lua_istable(L, 3)) { + pa_cvolume* volume = volume_from_lua(L, 3); + volume_to_lua(L, volume); + pa_xfree((void*) volume); + } else { + lua_pushvalue(L, 3); + } + + volume_t* vol = luaL_checkudata(L, -1, LUA_PA_VOLUME); + + // Move the volume userdata to the callback's thread. It needs to be kept alive + // until the callback has run. + lua_xmove(L, data->L, 1); pa_operation* op = - pa_context_set_sink_volume_by_index(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + pa_context_set_sink_volume_by_index(ctx->context, (uint32_t) index - 1, &vol->inner, success_callback, data); if (op == NULL) { int error = pa_context_errno(ctx->context); lua_pushvalue(L, 2); @@ -240,11 +263,6 @@ int context_set_sink_volume_by_index(lua_State* L) { lua_call(L, 1, 0); } - // TODO: Is this too early? - // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. - // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. - pa_xfree((void*) volume); - return 0; } @@ -569,9 +587,22 @@ int context_set_source_volume_by_name(lua_State* L) { simple_callback_data* data = prepare_lua_callback(L, 4); const char* name = luaL_checkstring(L, 2); - pa_cvolume* volume = volume_from_lua(L, 3); - pa_operation* op = pa_context_set_source_volume_by_name(ctx->context, name, volume, success_callback, data); + if (lua_istable(L, 3)) { + pa_cvolume* volume = volume_from_lua(L, 3); + volume_to_lua(L, volume); + pa_xfree((void*) volume); + } else { + lua_pushvalue(L, 3); + } + + volume_t* vol = luaL_checkudata(L, -1, LUA_PA_VOLUME); + + // Move the volume userdata to the callback's thread. It needs to be kept alive + // until the callback has run. + lua_xmove(L, data->L, 1); + + pa_operation* op = pa_context_set_source_volume_by_name(ctx->context, name, &vol->inner, success_callback, data); if (op == NULL) { int error = pa_context_errno(ctx->context); lua_pushvalue(L, 2); @@ -579,11 +610,6 @@ int context_set_source_volume_by_name(lua_State* L) { lua_call(L, 1, 0); } - // TODO: Is this too early? - // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. - // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. - pa_xfree((void*) volume); - return 0; } @@ -603,10 +629,23 @@ int context_set_source_volume_by_index(lua_State* L) { } simple_callback_data* data = prepare_lua_callback(L, 4); - pa_cvolume* volume = volume_from_lua(L, 3); + + if (lua_istable(L, 3)) { + pa_cvolume* volume = volume_from_lua(L, 3); + volume_to_lua(L, volume); + pa_xfree((void*) volume); + } else { + lua_pushvalue(L, 3); + } + + volume_t* vol = luaL_checkudata(L, -1, LUA_PA_VOLUME); + + // Move the volume userdata to the callback's thread. It needs to be kept alive + // until the callback has run. + lua_xmove(L, data->L, 1); pa_operation* op = - pa_context_set_source_volume_by_index(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + pa_context_set_source_volume_by_index(ctx->context, (uint32_t) index - 1, &vol->inner, success_callback, data); if (op == NULL) { int error = pa_context_errno(ctx->context); lua_pushvalue(L, 2); @@ -614,11 +653,6 @@ int context_set_source_volume_by_index(lua_State* L) { lua_call(L, 1, 0); } - // TODO: Is this too early? - // It's probably fine when the operation failed, but in the other case, this might have to be moved to the callback. - // But once this is userdata, I can simply put it onto the callback's thread stack and have Lua garbage collect it. - pa_xfree((void*) volume); - return 0; } @@ -983,12 +1017,25 @@ int context_set_sink_input_volume(lua_State* L) { if (index < 1) { return luaL_error(L, "Sink input index out of bounds. Got %d", index); } - pa_cvolume* volume = volume_from_lua(L, 3); simple_callback_data* data = prepare_lua_callback(L, 4); + if (lua_istable(L, 3)) { + pa_cvolume* volume = volume_from_lua(L, 3); + volume_to_lua(L, volume); + pa_xfree((void*) volume); + } else { + lua_pushvalue(L, 3); + } + + volume_t* vol = luaL_checkudata(L, -1, LUA_PA_VOLUME); + + // Move the volume userdata to the callback's thread. It needs to be kept alive + // until the callback has run. + lua_xmove(L, data->L, 1); + pa_operation* op = - pa_context_set_sink_input_volume(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + pa_context_set_sink_input_volume(ctx->context, (uint32_t) index - 1, &vol->inner, success_callback, data); if (op == NULL) { int error = pa_context_errno(ctx->context); lua_pushvalue(L, 2); @@ -1243,12 +1290,25 @@ int context_set_source_output_volume(lua_State* L) { if (index < 1) { return luaL_error(L, "Source output index out of bounds. Got %d", index); } - pa_cvolume* volume = volume_from_lua(L, 3); simple_callback_data* data = prepare_lua_callback(L, 4); + if (lua_istable(L, 3)) { + pa_cvolume* volume = volume_from_lua(L, 3); + volume_to_lua(L, volume); + pa_xfree((void*) volume); + } else { + lua_pushvalue(L, 3); + } + + volume_t* vol = luaL_checkudata(L, -1, LUA_PA_VOLUME); + + // Move the volume userdata to the callback's thread. It needs to be kept alive + // until the callback has run. + lua_xmove(L, data->L, 1); + pa_operation* op = - pa_context_set_source_output_volume(ctx->context, (uint32_t) index - 1, volume, success_callback, data); + pa_context_set_source_output_volume(ctx->context, (uint32_t) index - 1, &vol->inner, success_callback, data); if (op == NULL) { int error = pa_context_errno(ctx->context); lua_pushvalue(L, 2); From 5b3559bf0e67d6483b0a3ff7cd0356aeb5320192 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 22 Jun 2022 15:33:02 +0200 Subject: [PATCH 25/44] doc: Add disclaimer about current project state --- README.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 69dbf9a..77416f8 100644 --- a/README.adoc +++ b/README.adoc @@ -31,6 +31,10 @@ image:{url-luarocks-badge}[LuaRocks Package, link={url-luarocks-link}] https://freedesktop.org/software/pulseaudio/doxygen/index.html[libpulse] bindings for use with a GLib MainLoop via https://github.com/lgi-devs/lgi/[LGI]. +The project is still in a development state. It hasn't been fully tested yet, and not all functions from libpulse +have a corresponding binding yet. +Please do report anything that's missing or not working correctly. + == Quick Start Install https://github.com/lgi-devs/lgi[lgi] and _lua_libpulse_glib_ from LuaRocks: @@ -38,7 +42,7 @@ Install https://github.com/lgi-devs/lgi[lgi] and _lua_libpulse_glib_ from LuaRoc [source,shell] ---- luarocks install lgi -luarocks install lua-libpulse-glib +luarocks install --dev lua-libpulse-glib ---- [source,lua] From 5a981b821275c3d1c4ca75d4ebeb1b084c2a7c79 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 10 Aug 2022 13:05:46 +0200 Subject: [PATCH 26/44] bug: Fix installing --- Makefile | 2 +- spec/.gitkeep | 0 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 spec/.gitkeep diff --git a/Makefile b/Makefile index 24f8559..be29bdd 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,7 @@ clean: install: build doc @echo "\033[1;97mInstall C library\033[0m" - xargs install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) $(TARGET) + install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) $(TARGET) @echo "\033[1;97mInstall documentation\033[0m" install -vd $(INSTALL_DOCDIR) diff --git a/spec/.gitkeep b/spec/.gitkeep new file mode 100644 index 0000000..e69de29 From 243c50f921a663611102ce044efc94312616e08e Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 10 Aug 2022 13:55:48 +0200 Subject: [PATCH 27/44] chore: Ignore SASS cache --- .fdignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.fdignore b/.fdignore index 89f9ac0..e771cd6 100644 --- a/.fdignore +++ b/.fdignore @@ -1 +1,2 @@ out/ +.sass-cache/ From 8fa6f47cfe984336fa6e3d854c1bef357a4f4b28 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 10 Aug 2022 13:56:24 +0200 Subject: [PATCH 28/44] build: Only rebuild docs on changes --- Makefile | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index be29bdd..16592a0 100644 --- a/Makefile +++ b/Makefile @@ -63,18 +63,23 @@ $(TARGET): $(OBJS) @echo "\033[1;97m$(CC) -o $@\033[0m" @$(CC) $(LIBFLAG) -o $@ $(OBJS) $(LIBS) -doc-styles: - @echo "\033[1;97mGenerate stylesheet\033[0m" - sass doc/ldoc.scss $(BUILD_DIR)/doc/ldoc.css - -doc-content: +$(BUILD_DIR)/doc/index.html: @mkdir -p "$(BUILD_DIR)/doc" "$(BUILD_DIR)/src" @echo "\033[1;97mPreprocess sources\033[0m" sh tools/process_docs.sh "$(BUILD_DIR)" @echo "\033[1;97mGenerate documentation\033[0m" ldoc --config=doc/config.ld --dir "$(BUILD_DIR)/doc" --project $(PROJECT) "$(BUILD_DIR)/src" -doc: doc-content doc-styles +$(BUILD_DIR)/doc/ldoc.css: doc/ldoc.scss + @mkdir -p "$(BUILD_DIR)/doc" + @echo "\033[1;97mGenerate stylesheet\033[0m" + sass doc/ldoc.scss $(BUILD_DIR)/doc/ldoc.css + +doc-styles: $(BUILD_DIR)/doc/ldoc.css + +doc-content: $(BUILD_DIR)/doc/index.html + +doc: doc-styles doc-content ifdef CI touch "$(BUILD_DIR)/doc/.nojekyll" endif @@ -84,7 +89,7 @@ clean: install: build doc @echo "\033[1;97mInstall C library\033[0m" - install -vDm 644 -t $(INSTALL_LIBDIR)/$(PROJECT) $(TARGET) + install -vDm 644 -t $(INSTALL_LIBDIR) $(TARGET) @echo "\033[1;97mInstall documentation\033[0m" install -vd $(INSTALL_DOCDIR) From d10b61eaf9b2939ec34759fa46df94c1ad3c6d4f Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 10 Aug 2022 13:56:58 +0200 Subject: [PATCH 29/44] build: Add target to uninstall --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 16592a0..0e47432 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ TEST_ARGS ?= --output=TAP CCFLAGS += -Werror endif -.PHONY: clean doc doc-content doc-styles install test check rock +.PHONY: clean doc doc-content doc-styles install uninstall test check rock build: $(TARGET) @@ -95,6 +95,10 @@ install: build doc install -vd $(INSTALL_DOCDIR) cp -vr $(BUILD_DIR)/doc/* $(INSTALL_DOCDIR) +uninstall: + rm $(INSTALL_LIBDIR)/$(PROJECT).so + rm -r $(INSTALL_DOCDIR) + check: @echo "Nothing to do" From 862a265a707f49c8989b4a0dcdbad8ed3c810af8 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 10 Aug 2022 13:57:15 +0200 Subject: [PATCH 30/44] bug: Fix version incompatibility Even between minor versions, Lua simply removes or renames functions. --- src/lua_libpulse_glib/context.c | 5 +++-- src/lua_libpulse_glib/introspection.c | 8 ++++---- src/lua_libpulse_glib/lua_util.h | 7 +++++++ src/lua_libpulse_glib/volume.c | 4 ++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/lua_libpulse_glib/context.c b/src/lua_libpulse_glib/context.c index 34eba5d..5998431 100644 --- a/src/lua_libpulse_glib/context.c +++ b/src/lua_libpulse_glib/context.c @@ -1,6 +1,7 @@ #include "context.h" #include "pulseaudio.h" +#include "lua_util.h" #include #include @@ -196,7 +197,7 @@ int context_subscribe(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); luaL_checktype(L, 2, LUA_TFUNCTION); - size_t pos = lua_objlen(ctx->event_callback_data->L, 1) + 1; + size_t pos = lua_rawlen(ctx->event_callback_data->L, 1) + 1; // Duplicate the callback function, so we can move it over to the other thread lua_pushvalue(L, 2); lua_xmove(L, ctx->event_callback_data->L, 1); @@ -211,7 +212,7 @@ int context_unsubscribe(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); lua_State* thread_L = ctx->event_callback_data->L; size_t pos = 0; - size_t len = lua_objlen(thread_L, 1); + size_t len = lua_rawlen(thread_L, 1); if (len == 0) { return 0; diff --git a/src/lua_libpulse_glib/introspection.c b/src/lua_libpulse_glib/introspection.c index d404dd9..a77eb2a 100644 --- a/src/lua_libpulse_glib/introspection.c +++ b/src/lua_libpulse_glib/introspection.c @@ -55,7 +55,7 @@ void sink_info_callback(pa_context* c, const pa_sink_info* info, int eol, void* if (data->is_list) { if (!eol) { - int i = lua_objlen(L, 2); + int i = lua_rawlen(L, 2); lua_pushinteger(L, i + 1); sink_info_to_lua(L, info); lua_settable(L, 2); @@ -446,7 +446,7 @@ void source_info_callback(pa_context* c, const pa_source_info* info, int eol, vo if (data->is_list) { if (!eol) { - int i = lua_objlen(L, 2); + int i = lua_rawlen(L, 2); lua_pushinteger(L, i + 1); source_info_to_lua(L, info); lua_settable(L, 2); @@ -827,7 +827,7 @@ void sink_input_info_callback(pa_context* c, const pa_sink_input_info* info, int if (data->is_list) { if (!eol) { - int i = lua_objlen(L, 2); + int i = lua_rawlen(L, 2); lua_pushinteger(L, i + 1); sink_input_info_to_lua(L, info); lua_settable(L, 2); @@ -1100,7 +1100,7 @@ void source_output_info_callback(pa_context* c, const pa_source_output_info* inf if (data->is_list) { if (!eol) { - int i = lua_objlen(L, 2); + int i = lua_rawlen(L, 2); lua_pushinteger(L, i + 1); source_output_info_to_lua(L, info); lua_settable(L, 2); diff --git a/src/lua_libpulse_glib/lua_util.h b/src/lua_libpulse_glib/lua_util.h index 139d8cd..6128b41 100644 --- a/src/lua_libpulse_glib/lua_util.h +++ b/src/lua_libpulse_glib/lua_util.h @@ -6,6 +6,13 @@ #define LUA_MOD_EXPORT extern +#if LUA_VERSION_NUM <= 501 +#define lua_rawlen lua_objlen +#endif + +#if LUA_VERSION_NUM > 501 +#define lua_equal(L, i1, i2) lua_compare(L, i1, i2, LUA_OPEQ) +#endif typedef struct luaU_enumfield { const char* name; diff --git a/src/lua_libpulse_glib/volume.c b/src/lua_libpulse_glib/volume.c index 8421280..5183aeb 100644 --- a/src/lua_libpulse_glib/volume.c +++ b/src/lua_libpulse_glib/volume.c @@ -35,7 +35,7 @@ int volume_to_lua(lua_State* L, const pa_cvolume* pa_volume) { pa_cvolume* volume_from_lua(lua_State* L, int index) { switch (lua_type(L, index)) { case LUA_TTABLE: { - uint8_t channels = (uint8_t) lua_objlen(L, index); + uint8_t channels = (uint8_t) lua_rawlen(L, index); if (channels > PA_CHANNELS_MAX) { channels = PA_CHANNELS_MAX; } @@ -82,7 +82,7 @@ int volume__eq(lua_State* L) { int volume__index(lua_State* L) { volume_t* volume = luaL_checkudata(L, 1, LUA_PA_VOLUME); - int index = luaL_checkint(L, 2); + int index = (int) luaL_checkinteger(L, 2); luaL_argcheck(L, index >= 1 && index <= (PA_CHANNELS_MAX + 1), 2, "channel index out of bounds"); lua_pushinteger(L, volume->inner.values[index - 1]); return 1; From 3173460b1714b0083b016bc32609884e0c44ae60 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 10 Aug 2022 23:47:16 +0200 Subject: [PATCH 31/44] bug(volume): Fix constructor documentation --- src/lua_libpulse_glib/volume.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_libpulse_glib/volume.h b/src/lua_libpulse_glib/volume.h index e529143..c07ad47 100644 --- a/src/lua_libpulse_glib/volume.h +++ b/src/lua_libpulse_glib/volume.h @@ -49,6 +49,7 @@ int volume__newindex(lua_State*); /** Creates an instance of @{Volume}. * + * @function new * @tparam table values An array of channel volumes. * @treturn Volume */ From 1745e5d4adf5b17b2a605413a760109e48fdb06c Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Thu, 11 Aug 2022 13:37:00 +0200 Subject: [PATCH 32/44] feat(volume): Add conversion functions --- src/lua_libpulse_glib/volume.c | 30 ++++++++++++++++++ src/lua_libpulse_glib/volume.h | 58 +++++++++++++++++++++++++++++++--- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/lua_libpulse_glib/volume.c b/src/lua_libpulse_glib/volume.c index 5183aeb..d4aecab 100644 --- a/src/lua_libpulse_glib/volume.c +++ b/src/lua_libpulse_glib/volume.c @@ -1,5 +1,7 @@ #include "volume.h" +#include "lua_util.h" + #include #include #include @@ -311,3 +313,31 @@ int volume_divide(lua_State* L) { } } } + + +int volume_from_dB(lua_State* L) { + double value = (double) luaL_checknumber(L, 1); + lua_pushinteger(L, pa_sw_volume_from_dB(value)); + return 1; +} + + +int volume_to_dB(lua_State* L) { + pa_volume_t value = luaL_checkinteger(L, 1); + lua_pushnumber(L, pa_sw_volume_to_dB(value)); + return 1; +} + + +int volume_from_linear(lua_State* L) { + double value = (double) luaL_checknumber(L, 1); + lua_pushinteger(L, pa_sw_volume_from_linear(value)); + return 1; +} + + +int volume_to_linear(lua_State* L) { + pa_volume_t value = luaL_checkinteger(L, 1); + lua_pushnumber(L, pa_sw_volume_to_linear(value)); + return 1; +} diff --git a/src/lua_libpulse_glib/volume.h b/src/lua_libpulse_glib/volume.h index c07ad47..95c2870 100644 --- a/src/lua_libpulse_glib/volume.h +++ b/src/lua_libpulse_glib/volume.h @@ -55,7 +55,6 @@ int volume__newindex(lua_State*); */ int volume_new(lua_State*); - /** Checks whether a value is a valid @{Volume}. * * @function is_valid @@ -64,6 +63,53 @@ int volume_new(lua_State*); */ int volume_is_valid(lua_State*); +/** Converts a decibel value to an integer volume value. + * + * This is only valid for software volumes. It does not operate + * on instances of @{Volume}. + * + * @function from_dB + * @tparam number value + * @treturn number + */ +int volume_from_dB(lua_State*); + +/** Converts an integer volume value to a decibel value. + * + * This is only valid for software volumes. It does not operate + * on instances of @{Volume}. + * + * @function to_dB + * @tparam number value + * @treturn number + */ +int volume_to_dB(lua_State*); + +/** Converts a linear factor to an integer volume value. + * + * `0.0` and less is muted, `1.0` is normal volume. + * + * This is only valid for software volumes. It does not operate + * on instances of @{Volume}. + * + * @function from_linear + * @tparam number value + * @treturn number + */ +int volume_from_linear(lua_State*); + +/** Converts an integer volume value to linear factor. + * + * This is only valid for software volumes. It does not operate + * on instances of @{Volume}. + * + * @function to_linear + * @tparam number value + * @treturn number + */ +int volume_to_linear(lua_State*); + + /// Volume /// @type Volume @@ -236,9 +282,13 @@ static const struct luaL_Reg volume_mt[] = { static const struct luaL_Reg volume_lib[] = { - {"new", volume_new }, - { "is_valid", volume_is_valid}, - { NULL, NULL } + {"new", volume_new }, + { "from_dB", volume_from_dB }, + { "to_dB", volume_to_dB }, + { "from_linear", volume_from_linear}, + { "to_linear", volume_to_linear }, + { "is_valid", volume_is_valid }, + { NULL, NULL } }; From 7ea226fa51f5cceee135ff7ecf3977e76cc5d20b Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 14 Aug 2022 12:57:29 +0200 Subject: [PATCH 33/44] feat: Implement Concourse CI pipeline --- .busted.lua | 1 - .ci/pipeline.yml | 53 ++++++++++++++++++++++++++++++++ .ci/rock.sh | 14 +++++++++ .ci/rock.yml | 20 ++++++++++++ .ci/test.sh | 23 ++++++++++++++ .ci/test.yml | 20 ++++++++++++ Makefile | 4 ++- README.adoc | 8 ++--- src/lua_libpulse_glib/proplist.h | 2 ++ 9 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 .ci/pipeline.yml create mode 100755 .ci/rock.sh create mode 100644 .ci/rock.yml create mode 100755 .ci/test.sh create mode 100644 .ci/test.yml diff --git a/.busted.lua b/.busted.lua index 3aa0614..cfafed4 100644 --- a/.busted.lua +++ b/.busted.lua @@ -1,7 +1,6 @@ return { default = { verbose = true, - helper = "./spec/_helper.lua", lpath = "./src/?.lua;./src/?/init.lua;./src/?/?.lua;./tests/?.lua", }, } diff --git a/.ci/pipeline.yml b/.ci/pipeline.yml new file mode 100644 index 0000000..7e66b4e --- /dev/null +++ b/.ci/pipeline.yml @@ -0,0 +1,53 @@ +--- +resources: +- name: repo + type: git + icon: github + source: + uri: https://git.sclu1034.dev/lucas/lua-libpulse-glib + branch: ci + +jobs: +- name: test + plan: + - get: repo + trigger: true + - in_parallel: + - task: run-test-5.1 + file: repo/.ci/test.yml + vars: + lua-version: 5.1 + - task: run-test-5.2 + file: repo/.ci/test.yml + vars: + lua-version: 5.2 + - task: run-test-5.3 + file: repo/.ci/test.yml + vars: + lua-version: 5.3 + - task: run-test-5.4 + file: repo/.ci/test.yml + vars: + lua-version: 5.4 + +- name: rock + plan: + - get: repo + trigger: true + - in_parallel: + - task: run-rock-5.1 + file: repo/.ci/rock.yml + vars: + lua-version: 5.1 + - task: run-rock-5.2 + file: repo/.ci/rock.yml + vars: + lua-version: 5.2 + - task: run-rock-5.3 + file: repo/.ci/rock.yml + vars: + lua-version: 5.3 + - task: run-rock-5.4 + file: repo/.ci/rock.yml + vars: + lua-version: 5.4 diff --git a/.ci/rock.sh b/.ci/rock.sh new file mode 100755 index 0000000..4e863aa --- /dev/null +++ b/.ci/rock.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -ex + +sudo enable-lua ${LUA_VERSION:-5.1} +eval "$(luarocks --lua-version ${LUA_VERSION:-5.1} path)" + +luarocks --lua-version ${LUA_VERSION:-5.1} install lgi +luarocks --lua-version ${LUA_VERSION:-5.1} install ldoc +luarocks --lua-version ${LUA_VERSION:-5.1} install lua-discount + +luarocks --lua-version ${LUA_VERSION:-5.1} make rocks/lua-libpulse-glib-scm-1.rockspec + +sudo disable-lua ${LUA_VERSION:-5.1} diff --git a/.ci/rock.yml b/.ci/rock.yml new file mode 100644 index 0000000..e8754b4 --- /dev/null +++ b/.ci/rock.yml @@ -0,0 +1,20 @@ + +--- +platform: linux + +image_resource: + type: registry-image + source: + repository: registry.local:5000/lua-clib-pulse + tag: latest + +inputs: +- name: repo + +params: + CI: true + LUA_VERSION: ((lua-version)) + +run: + path: .ci/rock.sh + dir: repo diff --git a/.ci/test.sh b/.ci/test.sh new file mode 100755 index 0000000..f07b1ff --- /dev/null +++ b/.ci/test.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +set -ex + +mkdir -p "${BUILD_DIR:-./build}" + +CMAKE_ARGS="" + +if [ -n "$CI" ]; then + CMAKE_ARGS="-DCI=ON" +fi + +sudo enable-lua ${LUA_VERSION:-5.1} +eval "$(luarocks --lua-version ${LUA_VERSION:-5.1} path)" + +luarocks --lua-version ${LUA_VERSION:-5.1} install busted +luarocks --lua-version ${LUA_VERSION:-5.1} install lgi +luarocks --lua-version ${LUA_VERSION:-5.1} install ldoc +luarocks --lua-version ${LUA_VERSION:-5.1} install lua-discount + +make -j $(nproc) -C ${SOURCE_DIR:-.} LUA_VERSION=${LUA_VERSION:-5.1} LUA=lua + +sudo disable-lua ${LUA_VERSION:-5.1} diff --git a/.ci/test.yml b/.ci/test.yml new file mode 100644 index 0000000..0b0dc5d --- /dev/null +++ b/.ci/test.yml @@ -0,0 +1,20 @@ +--- +platform: linux + +image_resource: + type: registry-image + source: + repository: registry.local:5000/lua-clib-pulse + tag: latest + +inputs: +- name: repo + +params: + CI: true + SOURCE_DIR: repo + BUILD_DIR: /tmp/build-output + LUA_VERSION: ((lua-version)) + +run: + path: repo/.ci/test.sh diff --git a/Makefile b/Makefile index 0e47432..a8899ee 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,9 @@ TEST_ARGS ?= --output=TAP CCFLAGS += -Werror endif -.PHONY: clean doc doc-content doc-styles install uninstall test check rock +.PHONY: all clean doc doc-content doc-styles install uninstall test check rock + +all: build doc build: $(TARGET) diff --git a/README.adoc b/README.adoc index 77416f8..0e4d6cb 100644 --- a/README.adoc +++ b/README.adoc @@ -5,7 +5,6 @@ ifdef::env-github,env-browser[] :toc: macro :toclevels: 1 endif::[] -ifdef::env-github[] :branch: master :status: :outfilesuffix: .adoc @@ -15,16 +14,15 @@ ifdef::env-github[] :note-caption: :paperclip: :tip-caption: :bulb: :warning-caption: :warning: -endif::[] -:url-ci-github: https://github.com/sclu1034/lua-libpulse-glib/actions -:url-ci-badge-github: https://img.shields.io/github/workflow/status/sclu1034/lua-libpulse-glib/Lint%20&%20Test?style=flat-square +:url-ci: https://ci.sclu1034.dev/teams/main/pipelines/lgi-libpulse-glib +:url-ci-badge: https://ci.sclu1034.dev/api/v1/teams/main/pipelines/lgi-libpulse-glib/badge :url-license-badge: https://img.shields.io/badge/license-GPLv3-brightgreen?style=flat-square :url-luarocks-badge: https://img.shields.io/luarocks/v/sclu1034/lua-libpulse-glib?style=flat-square :url-luarocks-link: https://luarocks.org/modules/sclu1034/lua-libpulse-glib image:{url-license-badge}[License] ifdef::status[] -image:{url-ci-badge-github}[Build Status (GitHub Actions), link={url-ci-github}] +image:{url-ci-badge}[Build Status (Concourse CI), link={url-ci}] endif::[] image:{url-luarocks-badge}[LuaRocks Package, link={url-luarocks-link}] diff --git a/src/lua_libpulse_glib/proplist.h b/src/lua_libpulse_glib/proplist.h index 15d2d31..4c3d3e2 100644 --- a/src/lua_libpulse_glib/proplist.h +++ b/src/lua_libpulse_glib/proplist.h @@ -310,7 +310,9 @@ static const struct luaU_enumfield proplist_enum[] = { { "FORMAT_RATE", PA_PROP_FORMAT_RATE }, { "FORMAT_CHANNELS", PA_PROP_FORMAT_CHANNELS }, { "FORMAT_CHANNEL_MAP", PA_PROP_FORMAT_CHANNEL_MAP }, +#if PA_CHECK_VERSION(15, 0, 0) { "CONTEXT_FORCE_DISABLE_SHM", PA_PROP_CONTEXT_FORCE_DISABLE_SHM }, { "BLUETOOTH_CODEC", PA_PROP_BLUETOOTH_CODEC }, +#endif { NULL, NULL } }; From b9cda2deba74f2b4809ec30880a574ad8a5e6e17 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 14 Aug 2022 17:19:29 +0200 Subject: [PATCH 34/44] feat(ci): Allow CI to fail for 5.4 LGI doesn't have a rock compatible with 5.4, yet. --- .ci/pipeline.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.ci/pipeline.yml b/.ci/pipeline.yml index 7e66b4e..dd5fb3d 100644 --- a/.ci/pipeline.yml +++ b/.ci/pipeline.yml @@ -25,10 +25,12 @@ jobs: file: repo/.ci/test.yml vars: lua-version: 5.3 - - task: run-test-5.4 - file: repo/.ci/test.yml - vars: - lua-version: 5.4 + # There is no rock for 5.4 LGI, yet. And I don't want to build that from source. + - try: + task: run-test-5.4 + file: repo/.ci/test.yml + vars: + lua-version: 5.4 - name: rock plan: @@ -47,7 +49,9 @@ jobs: file: repo/.ci/rock.yml vars: lua-version: 5.3 - - task: run-rock-5.4 - file: repo/.ci/rock.yml - vars: - lua-version: 5.4 + # There is no rock for 5.4 LGI, yet. And I don't want to build that from source. + - try: + task: run-rock-5.4 + file: repo/.ci/rock.yml + vars: + lua-version: 5.4 From ee86906dd49d071c945129598bc6fe583ab1971d Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 14 Aug 2022 17:32:04 +0200 Subject: [PATCH 35/44] chore: Remove unused files --- .github/workflows/ci.yml | 79 --------------------------- .github/workflows/deploy-to-pages.yml | 34 ------------ .vscode/c_cpp_properties.json | 21 ------- .vscode/settings.json | 10 ---- 4 files changed, 144 deletions(-) delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/deploy-to-pages.yml delete mode 100644 .vscode/c_cpp_properties.json delete mode 100644 .vscode/settings.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index ee8cc00..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Lint & Test - -on: - push: - branches: [ master, staging, trying ] - pull_request: - branches: [ master ] - -env: - CI: true - DEBIAN: noninteractive - -jobs: - check: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2.4.0 - - uses: leafo/gh-actions-lua@v8.0.0 - - uses: leafo/gh-actions-luarocks@v4.0.0 - - - name: Install LuaCheck - run: luarocks install luacheck - - - name: Run checks - run: make check LUA_VERSION=${{ matrix.lua_version }} - - test: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - - lua_version: '5.1' - - lua_version: '5.2' - - lua_version: '5.3' - - lua_version: 'luajit' - steps: - - uses: actions/checkout@v2.4.0 - - uses: leafo/gh-actions-lua@v8.0.0 - with: - luaVersion: ${{ matrix.lua_version }} - - uses: leafo/gh-actions-luarocks@v4.0.0 - - - name: Install dependencies - shell: /bin/bash -o errexit -o pipefail -o xtrace {0} - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends gobject-introspection libgirepository1.0-dev libpulse-dev - luarocks install busted - luarocks install lgi - - - name: Run tests - run: make test LUA_VERSION=${{ matrix.lua_version }} - - rock: - runs-on: ubuntu-20.04 - needs: [test, check] - strategy: - fail-fast: false - matrix: - include: - - lua_version: '5.1' - - lua_version: '5.2' - - lua_version: '5.3' - steps: - - uses: actions/checkout@v2.4.0 - - uses: leafo/gh-actions-lua@v8.0.0 - with: - luaVersion: ${{ matrix.lua_version }} - - uses: leafo/gh-actions-luarocks@v4.0.0 - - - name: Install dependencies - shell: /bin/bash -o errexit -o pipefail -o xtrace {0} - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends gobject-introspection libgirepository1.0-dev - - - name: Make rock - run: make rock LUA_VERSION=${{ matrix.lua_version }} diff --git a/.github/workflows/deploy-to-pages.yml b/.github/workflows/deploy-to-pages.yml deleted file mode 100644 index 51176b0..0000000 --- a/.github/workflows/deploy-to-pages.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Deploy docs - -on: - push: - branches: ['master'] - -env: - DEBIAN: noninteractive - -jobs: - deploy-docs: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2.4.0 - - uses: leafo/gh-actions-lua@v8.0.0 - - uses: leafo/gh-actions-luarocks@v4.0.0 - - uses: actions/setup-node@v2 - with: - node-version: 'lts/*' - - - name: Install dependencies - run: | - luarocks install ldoc - luarocks install lua-discount - npm install --global sass - - - name: Generate documentation - run: make doc - - - name: Deploy to gh-pages - uses: JamesIves/github-pages-deploy-action@v4.2.5 - with: - branch: gh-pages - folder: out/doc diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 0b51fe3..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/src/lua_libpulse_glib/**", - "/usr/include/lua5.3", - "/usr/include/glib-2.0", - "/usr/lib/glib-2.0/include", - "/usr/lib/x86_64-linux-gnu/glib-2.0/include", - "/usr/include/gobject-introspection-1.0" - ], - "defines": [], - "compilerPath": "/usr/bin/gcc", - "cStandard": "c11", - "cppStandard": "c++14", - "intelliSenseMode": "linux-clang-x64" - } - ], - "version": 4 -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index db3ee7e..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "C_Cpp.errorSquiggles": "Enabled", - "files.associations": { - "**/tasks/*.yml": "ansible", - "*.rockspec": "lua", - "*.ld": "lua", - "glib-mainloop.h": "c", - "lua.h": "c" - } -} From 2152186e2384fb58dc13b3d4ef2c0ae0b350ca3e Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 14 Aug 2022 17:35:51 +0200 Subject: [PATCH 36/44] ci: Switch to master branch --- .ci/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/pipeline.yml b/.ci/pipeline.yml index dd5fb3d..10f7488 100644 --- a/.ci/pipeline.yml +++ b/.ci/pipeline.yml @@ -5,7 +5,7 @@ resources: icon: github source: uri: https://git.sclu1034.dev/lucas/lua-libpulse-glib - branch: ci + branch: master jobs: - name: test From b46efff6225e13a1cf4e4059c6f523f57369d6d5 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 14 Aug 2022 17:37:17 +0200 Subject: [PATCH 37/44] doc: Fix CI badge --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 0e4d6cb..03b2813 100644 --- a/README.adoc +++ b/README.adoc @@ -14,8 +14,8 @@ endif::[] :note-caption: :paperclip: :tip-caption: :bulb: :warning-caption: :warning: -:url-ci: https://ci.sclu1034.dev/teams/main/pipelines/lgi-libpulse-glib -:url-ci-badge: https://ci.sclu1034.dev/api/v1/teams/main/pipelines/lgi-libpulse-glib/badge +:url-ci: https://ci.sclu1034.dev/teams/main/pipelines/lua-libpulse-glib +:url-ci-badge: https://ci.sclu1034.dev/api/v1/teams/main/pipelines/lua-libpulse-glib/badge :url-license-badge: https://img.shields.io/badge/license-GPLv3-brightgreen?style=flat-square :url-luarocks-badge: https://img.shields.io/luarocks/v/sclu1034/lua-libpulse-glib?style=flat-square :url-luarocks-link: https://luarocks.org/modules/sclu1034/lua-libpulse-glib From 7e96f344bea829f9ae0fccd22830d4f3f0eb295e Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 14 Aug 2022 17:37:57 +0200 Subject: [PATCH 38/44] chore: Remove unused Bors config --- bors.toml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 bors.toml diff --git a/bors.toml b/bors.toml deleted file mode 100644 index 85d5802..0000000 --- a/bors.toml +++ /dev/null @@ -1,10 +0,0 @@ -status = [ - "check", - "test (5.1)", - "test (5.2)", - "test (5.3)", - "test (luajit)", - "rock (5.1)", - "rock (5.2)", - "rock (5.3)", -] From 45a1c9b71199b02fc3e857c88db10f2958a9f449 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 17 Aug 2022 15:07:59 +0200 Subject: [PATCH 39/44] ci: Only build the library for testing The docs don't need to be build for that. --- .ci/test.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.ci/test.sh b/.ci/test.sh index f07b1ff..fd886fb 100755 --- a/.ci/test.sh +++ b/.ci/test.sh @@ -15,9 +15,7 @@ eval "$(luarocks --lua-version ${LUA_VERSION:-5.1} path)" luarocks --lua-version ${LUA_VERSION:-5.1} install busted luarocks --lua-version ${LUA_VERSION:-5.1} install lgi -luarocks --lua-version ${LUA_VERSION:-5.1} install ldoc -luarocks --lua-version ${LUA_VERSION:-5.1} install lua-discount -make -j $(nproc) -C ${SOURCE_DIR:-.} LUA_VERSION=${LUA_VERSION:-5.1} LUA=lua +make -j $(nproc) -C ${SOURCE_DIR:-.} BUILD_DIR=${BUILD_DIR:-./build} LUA_VERSION=${LUA_VERSION:-5.1} LUA=lua build sudo disable-lua ${LUA_VERSION:-5.1} From c8bf8931c84cb00ef349718900042fffcf5f4002 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 17 Aug 2022 15:13:56 +0200 Subject: [PATCH 40/44] ci: Build and deploy documentation --- .ci/deploy-docs.sh | 22 ++++++++++++++++++++++ .ci/deploy-docs.yml | 22 ++++++++++++++++++++++ .ci/pipeline.yml | 11 +++++++++++ Makefile | 3 --- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100755 .ci/deploy-docs.sh create mode 100644 .ci/deploy-docs.yml diff --git a/.ci/deploy-docs.sh b/.ci/deploy-docs.sh new file mode 100755 index 0000000..687d2e9 --- /dev/null +++ b/.ci/deploy-docs.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +mkdir -p "${BUILD_DIR:-./build}" + +CMAKE_ARGS="" + +if [ -n "$CI" ]; then + CMAKE_ARGS="-DCI=ON" +fi + +sudo enable-lua ${LUA_VERSION:-5.1} + +make -j $(nproc) -C ${SOURCE_DIR:-.} BUILD_DIR=${BUILD_DIR:-./build} LUA_VERSION=${LUA_VERSION:-5.1} LUA=lua doc + +tar -czf doc.tar.gz -C ${BUILD_DIR:-./build}/doc . + +curl -T doc.tar.gz -XPOST --user ${DOCS_CREDENTIALS} https://${DOCS_HOST}/publish/lua-libpulse-glib + +sudo disable-lua ${LUA_VERSION:-5.1} + diff --git a/.ci/deploy-docs.yml b/.ci/deploy-docs.yml new file mode 100644 index 0000000..3cb49d6 --- /dev/null +++ b/.ci/deploy-docs.yml @@ -0,0 +1,22 @@ +--- +platform: linux + +image_resource: + type: registry-image + source: + repository: registry.local:5000/lua-clib-pulse + tag: latest + +inputs: +- name: repo + +params: + CI: true + SOURCE_DIR: repo + BUILD_DIR: /tmp/build-output + DOCS_HOST: ((doc-host)) + DOCS_CREDENTIALS: "((deploy-user)):((deploy-password))" + +run: + path: repo/.ci/deploy-docs.sh + diff --git a/.ci/pipeline.yml b/.ci/pipeline.yml index 10f7488..ced9a29 100644 --- a/.ci/pipeline.yml +++ b/.ci/pipeline.yml @@ -55,3 +55,14 @@ jobs: file: repo/.ci/rock.yml vars: lua-version: 5.4 + +- name: doc + plan: + - get: repo + trigger: true + - task: deploy-docs + file: repo/.ci/deploy-docs.yml + params: + doc-host: ((doc-host)) + deploy-user: ((deploy-user)) + deploy-password: ((deploy-password)) diff --git a/Makefile b/Makefile index a8899ee..d2a1cd1 100644 --- a/Makefile +++ b/Makefile @@ -82,9 +82,6 @@ doc-styles: $(BUILD_DIR)/doc/ldoc.css doc-content: $(BUILD_DIR)/doc/index.html doc: doc-styles doc-content -ifdef CI - touch "$(BUILD_DIR)/doc/.nojekyll" -endif clean: rm -r out/ From 3838b9f52a031d921610d49138261d8269e546e8 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Thu, 18 Aug 2022 13:31:49 +0200 Subject: [PATCH 41/44] bug(ci): Fix passing variables to task --- .ci/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/pipeline.yml b/.ci/pipeline.yml index ced9a29..51048e7 100644 --- a/.ci/pipeline.yml +++ b/.ci/pipeline.yml @@ -62,7 +62,7 @@ jobs: trigger: true - task: deploy-docs file: repo/.ci/deploy-docs.yml - params: + vars: doc-host: ((doc-host)) deploy-user: ((deploy-user)) deploy-password: ((deploy-password)) From 30db8863e3f92abb43f77dde892634c5d1f0e838 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 1 Nov 2023 20:24:06 +0100 Subject: [PATCH 42/44] Fix module initialization The way C modules are initialized was affected by one of the major breaking changes between 5.x versions. Rather than trying to cater to each version individually, we now just backport from newer versions. Namely from 5.2 to 5.1. --- src/lua_libpulse_glib/callback.h | 7 +----- src/lua_libpulse_glib/lua_util.h | 9 +++---- src/lua_libpulse_glib/pulseaudio.c | 39 +++++------------------------- 3 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/lua_libpulse_glib/callback.h b/src/lua_libpulse_glib/callback.h index 97ced0f..60c90b8 100644 --- a/src/lua_libpulse_glib/callback.h +++ b/src/lua_libpulse_glib/callback.h @@ -1,6 +1,4 @@ -#ifndef callback_h_INCLUDED -#define callback_h_INCLUDED - +#pragma once #include #include @@ -40,6 +38,3 @@ void free_lua_callback(simple_callback_data*); // Simple implementation of `pa_context_success_cb_t` that calls a provided Lua function. void success_callback(pa_context*, int, void*); - -#endif // callback_h_INCLUDED - diff --git a/src/lua_libpulse_glib/lua_util.h b/src/lua_libpulse_glib/lua_util.h index 6128b41..0f05e11 100644 --- a/src/lua_libpulse_glib/lua_util.h +++ b/src/lua_libpulse_glib/lua_util.h @@ -1,5 +1,4 @@ -#ifndef lua_util_h_INCLUDED -#define lua_util_h_INCLUDED +#pragma once #include #include @@ -8,6 +7,9 @@ #if LUA_VERSION_NUM <= 501 #define lua_rawlen lua_objlen + +#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0)) +#define luaL_newlibtable(L, l) (lua_createtable(L, 0, sizeof(l) / sizeof(l[0]))) #endif #if LUA_VERSION_NUM > 501 @@ -18,6 +20,3 @@ typedef struct luaU_enumfield { const char* name; const char* value; } luaU_enumfield; - - -#endif // lua_util_h_INCLUDED diff --git a/src/lua_libpulse_glib/pulseaudio.c b/src/lua_libpulse_glib/pulseaudio.c index 6d6f266..d6b7368 100644 --- a/src/lua_libpulse_glib/pulseaudio.c +++ b/src/lua_libpulse_glib/pulseaudio.c @@ -10,10 +10,8 @@ #include #include - #if LUA_VERSION_NUM <= 501 // Shamelessly copied from Lua 5.3 source. -// TODO: What's the 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 */ @@ -29,12 +27,8 @@ void luaL_setfuncs(lua_State* L, const luaL_Reg* l, int nup) { } lua_pop(L, nup); /* remove upvalues */ } - - -#define luaL_newlib(L, l) (luaL_register(L, LUA_PULSEAUDIO, l)) #endif - int pulseaudio_new(lua_State* L) { GMainContext* ctx = g_main_context_default(); if (ctx == NULL) { @@ -86,17 +80,13 @@ int pulseaudio_new_context(lua_State* L) { void createlib_volume(lua_State* L) { luaL_newmetatable(L, LUA_PA_VOLUME); - lua_createtable(L, 0, sizeof volume_f / sizeof volume_f[0]); - luaL_setfuncs(L, volume_f, 0); + luaL_newlib(L, volume_f); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, volume_mt, 0); -#if LUA_VERSION_NUM <= 501 - luaL_register(L, LUA_PA_VOLUME, volume_lib); -#else luaL_newlib(L, volume_lib); -#endif + lua_setmetatable(L, -2); } @@ -104,17 +94,12 @@ void createlib_volume(lua_State* L) { void createlib_proplist(lua_State* L) { luaL_newmetatable(L, LUA_PA_PROPLIST); - lua_createtable(L, 0, sizeof proplist_f / sizeof proplist_f[0]); - luaL_setfuncs(L, proplist_f, 0); + luaL_newlib(L, proplist_f); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, proplist_mt, 0); -#if LUA_VERSION_NUM <= 501 - luaL_register(L, LUA_PA_PROPLIST, proplist_lib); -#else luaL_newlib(L, proplist_lib); -#endif // Create a metatable with an `__index` table for read-only enum fields. lua_createtable(L, 0, 1); @@ -133,8 +118,7 @@ void createlib_proplist(lua_State* L) { void createlib_context(lua_State* L) { luaL_newmetatable(L, LUA_PA_CONTEXT); - lua_createtable(L, 0, sizeof context_f / sizeof context_f[0]); - luaL_setfuncs(L, context_f, 0); + luaL_newlib(L, context_f); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, context_mt, 0); @@ -144,17 +128,12 @@ void createlib_context(lua_State* L) { void createlib_pulseaudio(lua_State* L) { luaL_newmetatable(L, LUA_PULSEAUDIO); - lua_createtable(L, 0, sizeof pulseaudio_f / sizeof pulseaudio_f[0]); - luaL_setfuncs(L, pulseaudio_f, 0); + luaL_newlib(L, pulseaudio_f); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, pulseaudio_mt, 0); -#if LUA_VERSION_NUM <= 501 - luaL_register(L, LUA_PULSEAUDIO, pulseaudio_lib); -#else luaL_newlib(L, pulseaudio_lib); -#endif } @@ -177,17 +156,11 @@ LUA_MOD_EXPORT int luaopen_lua_libpulse_glib(lua_State* L) { LUA_MOD_EXPORT int luaopen_lua_libpulse_glib_volume(lua_State* L) { luaL_newmetatable(L, LUA_PA_VOLUME); - lua_createtable(L, 0, sizeof volume_f / sizeof volume_f[0]); - luaL_setfuncs(L, volume_f, 0); + luaL_newlib(L, volume_f); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, volume_mt, 0); -#if LUA_VERSION_NUM <= 501 - luaL_register(L, LUA_PA_VOLUME, volume_lib); -#else luaL_newlib(L, volume_lib); -#endif return 1; } - From d2f424cbe2cc887a100f6bdbb0fa10fb51b66b01 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 1 Nov 2023 22:08:06 +0100 Subject: [PATCH 43/44] Improve running tests --- Makefile | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d2a1cd1..ad3e65f 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,8 @@ OBJS = $(shell find src -type f -iname '*.c' | sed 's/\(.*\)\.c$$/$(BUILD_DIR)\/ TARGET = $(BUILD_DIR)/$(PROJECT).so +LUA_CPATH = $(shell echo "$${PWD}/$(BUILD_DIR)/?.so;$${LUA_CPATH}") + ifdef CI CHECK_ARGS ?= --formatter TAP TEST_ARGS ?= --output=TAP @@ -50,6 +52,11 @@ TEST_ARGS ?= --output=TAP CCFLAGS += -Werror endif +bold := $(shell tput bold) +orange := $(shell tput setaf 7) +title := $(bold)$(orange) +reset := $(shell tput sgr0) + .PHONY: all clean doc doc-content doc-styles install uninstall test check rock all: build doc @@ -58,23 +65,23 @@ build: $(TARGET) $(BUILD_DIR)/%.o: %.c @mkdir -p $(shell dirname "$@") - @echo "\033[1;97m$(CC) $< -o $@\033[0m" + @echo "$(title)$(CC) $< -o $@$(reset)" @$(CC) -c $(CCFLAGS) $< -o $@ $(TARGET): $(OBJS) - @echo "\033[1;97m$(CC) -o $@\033[0m" + @echo "$(title)$(CC) -o $@$(reset)" @$(CC) $(LIBFLAG) -o $@ $(OBJS) $(LIBS) $(BUILD_DIR)/doc/index.html: @mkdir -p "$(BUILD_DIR)/doc" "$(BUILD_DIR)/src" - @echo "\033[1;97mPreprocess sources\033[0m" + @echo "$(title)Preprocess sources$(reset)" sh tools/process_docs.sh "$(BUILD_DIR)" - @echo "\033[1;97mGenerate documentation\033[0m" + @echo "$(title)Generate documentation$(reset)" ldoc --config=doc/config.ld --dir "$(BUILD_DIR)/doc" --project $(PROJECT) "$(BUILD_DIR)/src" $(BUILD_DIR)/doc/ldoc.css: doc/ldoc.scss @mkdir -p "$(BUILD_DIR)/doc" - @echo "\033[1;97mGenerate stylesheet\033[0m" + @echo "$(title)Generate stylesheet$(reset)" sass doc/ldoc.scss $(BUILD_DIR)/doc/ldoc.css doc-styles: $(BUILD_DIR)/doc/ldoc.css @@ -87,10 +94,10 @@ clean: rm -r out/ install: build doc - @echo "\033[1;97mInstall C library\033[0m" + @echo "$(title)Install C library\033[0m" install -vDm 644 -t $(INSTALL_LIBDIR) $(TARGET) - @echo "\033[1;97mInstall documentation\033[0m" + @echo "$(title)Install documentation\033[0m" install -vd $(INSTALL_DOCDIR) cp -vr $(BUILD_DIR)/doc/* $(INSTALL_DOCDIR) @@ -101,8 +108,11 @@ uninstall: check: @echo "Nothing to do" -test: +spec: build busted --config-file=.busted.lua --lua=$(LUA) $(TEST_ARGS) +test: build + $(LUA) test.lua + rock: luarocks --local --lua-version $(LUA_VERSION) make rocks/lua-libpulse-glib-scm-1.rockspec From aca076f51b0957e8640a9f8b2cec4a16d702a1c0 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Wed, 1 Nov 2023 22:09:12 +0100 Subject: [PATCH 44/44] Implement event subscription --- src/lua_libpulse_glib/context.c | 57 +++++++++++++++++++++++++++------ src/lua_libpulse_glib/context.h | 4 +++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/lua_libpulse_glib/context.c b/src/lua_libpulse_glib/context.c index 5998431..69a4cd9 100644 --- a/src/lua_libpulse_glib/context.c +++ b/src/lua_libpulse_glib/context.c @@ -1,7 +1,7 @@ #include "context.h" -#include "pulseaudio.h" #include "lua_util.h" +#include "pulseaudio.h" #include #include @@ -33,18 +33,29 @@ void context_event_callback(pa_context* c, pa_subscription_event_type_t event_ty simple_callback_data* data = (simple_callback_data*) userdata; lua_State* L = data->L; - luaL_checktype(L, 1, LUA_TFUNCTION); + luaL_checktype(L, 1, LUA_TTABLE); luaL_checkudata(L, 2, LUA_PA_CONTEXT); - // `lua_call` will pop the function and arguments from the stack, but this callback will likely be called - // multiple times. - // To preseve the values for future calls, we need to duplicate them. - lua_pushvalue(L, 1); - lua_pushvalue(L, 2); - lua_pushinteger(L, event_type); - lua_pushinteger(L, index); + // Iterate over the list of subscription callbacks and call each one + lua_pushnil(L); + while (lua_next(L, 1) != 0) { + // TODO: Once we do have the "nothing here" value, we need to check for that here. - lua_call(L, 3, 0); + // Copy the `self` parameter + lua_pushvalue(L, 2); + lua_pushinteger(L, event_type); + lua_pushinteger(L, index); + + lua_call(L, 3, 0); + } +} + + +void context_subscribe_success_callback(pa_context* _c, int success, void* userdata) { + simple_callback_data* data = (simple_callback_data*) userdata; + if (!success) { + luaL_error(data->L, "Failed to subscribe to events"); + } } @@ -62,6 +73,7 @@ int context_new(lua_State* L, pa_mainloop_api* pa_api) { } lgi_ctx->context = ctx; lgi_ctx->connected = FALSE; + lgi_ctx->subscribed = FALSE; lgi_ctx->state_callback_data = prepare_lua_callback(L, 0); lgi_ctx->event_callback_data = prepare_lua_callback(L, 0); @@ -71,6 +83,10 @@ int context_new(lua_State* L, pa_mainloop_api* pa_api) { luaL_getmetatable(L, LUA_PA_CONTEXT); lua_setmetatable(L, -2); + // Copy the `context` value to the event callback + lua_pushvalue(L, -1); + lua_xmove(L, lgi_ctx->event_callback_data->L, 1); + return 1; } @@ -197,8 +213,19 @@ int context_subscribe(lua_State* L) { lua_pa_context* ctx = luaL_checkudata(L, 1, LUA_PA_CONTEXT); luaL_checktype(L, 2, LUA_TFUNCTION); + // This call is only effective when the connection state is "ready". + // So we have to do it here, rather than during `context_connect`, + // but we also need to make sure it's only called once. + if (!ctx->subscribed) { + pa_context_subscribe(ctx->context, + PA_SUBSCRIPTION_MASK_ALL, + context_subscribe_success_callback, + ctx->event_callback_data); + } + size_t pos = lua_rawlen(ctx->event_callback_data->L, 1) + 1; // Duplicate the callback function, so we can move it over to the other thread + // TODO: Do we actually need to duplicate? lua_pushvalue(L, 2); lua_xmove(L, ctx->event_callback_data->L, 1); lua_rawseti(ctx->event_callback_data->L, 1, pos); @@ -218,6 +245,14 @@ int context_unsubscribe(lua_State* L) { return 0; } + // TODO: Handle calling this twice on the same index. + // Given that we use an array to track things, and Lua's way of counting in arrays + // doesn't like `nil`s, we probably need a special "nothing here" value that's not `nil`, + // and signifies an index that has already been unsubscribed. + + // TODO: Simplify things. Supporting just the index is enough. + // Comparing by function is convenient, but also confusing to inexperienced devs. + switch (lua_type(L, 2)) { case LUA_TNUMBER: { pos = lua_tointeger(L, 2); @@ -257,6 +292,8 @@ int context_unsubscribe(lua_State* L) { } } + // TODO: As explained above, we need to handle calling unsubscribe twice better. + // Indices should not be re-used but replaced by a special "nothing here" value. for (; pos < len; ++pos) { lua_rawgeti(thread_L, 1, pos + 1); lua_rawseti(thread_L, 1, pos); diff --git a/src/lua_libpulse_glib/context.h b/src/lua_libpulse_glib/context.h index dacd077..48ccb54 100644 --- a/src/lua_libpulse_glib/context.h +++ b/src/lua_libpulse_glib/context.h @@ -24,6 +24,7 @@ typedef struct lua_pa_context { pa_context* context; bool connected; + bool subscribed; simple_callback_data* state_callback_data; simple_callback_data* event_callback_data; } lua_pa_context; @@ -95,6 +96,9 @@ int context_get_state(lua_State*); * Any number of callbacks may be registered at the same time, and can be unscubscribed with * @{Context:unsubscribe}, using the returned subscription ID. * + * This must called after the connection state changed to "ready" (index `4`). Otherwise + * it will have no effect. + * * @function Context:subscribe * @tparam function cb * @treturn number The subscription ID.