// clang $(pkg-config --cflags taglib) $(pkg-config --libs taglib) -shared -o taglib-module.so taglib-module.cxx #include #include #include #include int plugin_is_GPL_compatible; static char* copy_lisp_string(emacs_env *env, emacs_value arg) { ptrdiff_t len; char *buf; if (!env->copy_string_contents(env, arg, NULL, &len)) { return NULL; } buf = (char *) malloc(len); if (!buf) { return NULL; } if (!env->copy_string_contents(env, arg, buf, &len)) { return NULL; } return buf; } static void bind_function(emacs_env *env, const char *name, emacs_value Sfun) { emacs_value Qfset = env->intern(env, "fset"); emacs_value Qsym = env->intern(env, name); emacs_value args[] = { Qsym, Sfun }; env->funcall(env, Qfset, 2, args); } static void provide(emacs_env *env, const char *feature) { emacs_value Qfeat = env->intern(env, feature); emacs_value Qprovide = env->intern (env, "provide"); emacs_value args[] = { Qfeat }; env->funcall(env, Qprovide, 1, args); } static emacs_value Ftaglib_test(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) noexcept { emacs_value Qnil = env->intern(env, "nil"); emacs_value ret = Qnil; char *path = copy_lisp_string(env, args[0]); TagLib::File *file = TagLib::FileRef::create(path); free(path); if (file && file->isValid()) { TagLib::String title = file->tag()->title(); if (title != TagLib::String::null) { char *title_str = strdup(title.to8Bit(true).c_str()); ret = env->make_string(env, title_str, strlen(title_str)); free(title_str); } } delete file; return ret; } int emacs_module_init(struct emacs_runtime *ert) { emacs_env *env = ert->get_environment(ert); bind_function(env, "taglib-test", env->make_function(env, 1, 1, Ftaglib_test, NULL, NULL)); provide(env, "taglib-module"); return 0; }