From a3569eabfc4e72c136c01c176dee70a3bc16638c Mon Sep 17 00:00:00 2001 From: Spencer Williams Date: Wed, 30 Jul 2025 13:08:29 -0400 Subject: Add Lua filter support --- Makefile | 2 +- README.md | 30 ++++++++++++++++++++++++++++++ mpc-bar.m | 41 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 1440a9b..2c35264 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ TARGET = mpc-bar CFLAGS = -O2 -fobjc-arc -Wall -LDFLAGS = -lmpdclient -framework Cocoa +LDFLAGS = -lmpdclient -llua -framework Cocoa OUTPUT_OPTION=-MMD -MP -o $@ BINDIR = /usr/local/bin diff --git a/README.md b/README.md index d643c90..ee3ae01 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,34 @@ format = [%name%: &[[%artist%|%performer%|%composer%|%albumartist%] - ]%title%]| idle_message = No song playing show_queue = true # Show queue/position info while playing? (true/false) show_queue_idle = (value of show_queue) # Show queue/position info while idle? (true/false) +# lua_filter = ~/.mpc-bar-filter.lua # Path to a Lua filter script ``` + +## Lua filter +Sometimes, especially with Internet radio, your MPD status can end up +a lot longer than it needs to be. MPC Bar lets you write a filter +script in Lua to massage the status into a more manageable form. +Here's an example: + +```lua +local subs = + { + {"^Groove Salad: a nicely chilled plate of ambient beats and grooves.", "[Groove Salad]"}, + {"^Drone Zone: Atmospheric ambient space music. Serve Best Chilled. Safe with most medications.", "[Drone Zone]"}, + {" %[SomaFM%]:", ""}, + } + +function filter(s) + for _, sub in ipairs(subs) do + s = s:gsub(sub[1], sub[2]) + end + return s +end +``` + +MPC Bar expects a global function called `filter`, which takes the +original MPD status and returns a new status to be used instead. + +Currently there is no provision for error reporting. If your code has +an error, MPC Bar will just use the original status. You might want +to test on your own with the standalone `lua` interpreter. diff --git a/mpc-bar.m b/mpc-bar.m index 91597ab..1a06a6d 100644 --- a/mpc-bar.m +++ b/mpc-bar.m @@ -20,6 +20,9 @@ #include "mpc/song_format.h" #include +#include +#include +#include #include #include #include @@ -27,7 +30,7 @@ #import -#define VERSION "0.4" +#define VERSION "0.5.0" #define TITLE_MAX_LENGTH 96 #define SLEEP_INTERVAL 0.2 @@ -46,7 +49,7 @@ static NSString *formatTime(unsigned int t) { } struct config { - const char *host, *password, *format, *idle_message; + const char *host, *password, *format, *idle_message, *lua_filter; int show_queue, show_queue_idle; unsigned port; }; @@ -69,6 +72,8 @@ static int handler(void *userdata, const char *section, const char *name, c->show_queue = (strcmp(value, "false") != 0); } else if (MATCH("display", "show_queue_idle")) { c->show_queue_idle = (strcmp(value, "false") != 0); + } else if (MATCH("display", "lua_filter")) { + c->lua_filter = strdup(value); } else { return 0; } @@ -95,6 +100,9 @@ static int handler(void *userdata, const char *section, const char *name, NSMenu *songMenu; NSMapTable *songMap; + + lua_State *L; + const char *luaFilterPath; } - (void)initConfig { config.host = "localhost"; @@ -121,6 +129,28 @@ static int handler(void *userdata, const char *section, const char *name, config.show_queue_idle = config.show_queue; } } +- (void)initLua { + if (config.lua_filter) { + L = luaL_newstate(); + luaL_openlibs(L); + luaFilterPath = [[utf8String(config.lua_filter) stringByStandardizingPath] + cStringUsingEncoding:NSUTF8StringEncoding]; + } +} +- (const char *)runLuaFilterOn:(const char *)s { + if (luaL_dofile(L, luaFilterPath) != LUA_OK) { + return s; + } + lua_getglobal(L, "filter"); + if (!lua_isfunction(L, -1)) { + return s; + } + lua_pushstring(L, s); + if (lua_pcall(L, 1, 1, 0) != LUA_OK) { + return s; + } + return lua_tostring(L, -1); +} - (void)connect { assert(connection == NULL); @@ -237,7 +267,11 @@ static int handler(void *userdata, const char *section, const char *name, [menuButton setImage:nil]; char *s = format_song(song, config.format); - [output appendString:utf8String(s)]; + if (L) { + [output appendString:utf8String([self runLuaFilterOn:s])]; + } else { + [output appendString:utf8String(s)]; + } free(s); } else { // FIXME: There's no point calling utf8String more than once, as @@ -442,6 +476,7 @@ cleanup: if (self = [super init]) { [self initConfig]; [self readConfigFile]; + [self initLua]; [self connect]; [self initSongMenu]; [self initControlMenu]; -- cgit v1.2.3