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 0000000..e19e247 Binary files /dev/null and b/lua.debug differ diff --git a/src/lua_libpulse_glib/introspection.c b/src/lua_libpulse_glib/introspection.c index b92dc13..0b4e1bc 100644 --- a/src/lua_libpulse_glib/introspection.c +++ b/src/lua_libpulse_glib/introspection.c @@ -14,6 +14,320 @@ typedef struct server_info_callback_data { } server_info_callback_data; +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 +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()