/* * Feynman -- Wayland compositor for GNU Emacs * * Copyright (c) 2022 Sameer Rahmani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "compositor.h" #include "export.h" #include "queue.h" #include "utils.h" #include #include /* Declare mandatory GPL symbol. */ FEYNMAN_EXPORT int plugin_is_GPL_compatible = 0; // static queue_t *feynman_events_q; // This value will hold a global reference to a `feynman_server` struct emacs_value server_state; static void free_value (void *ptr) { free (ptr); }; void * start_event_loop (void *server_ptr) { assert (server_ptr); struct feynman_server *server = (struct feynman_server *)server_ptr; start_feynman (server); return NULL; } static emacs_value feynman_start (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) { (void)nargs; (void)args; (void)data; emacs_value nil = env->intern (env, "nil"); struct feynman_server *server = malloc (sizeof (struct feynman_server)); int err = init_feynman_server (env, server); if (err != 0) { em_error (env, "Start process failed.Received none zero error code: %d", err); return nil; } // feynman_events_q = (queue_t *)init_queue(100); pthread_create (&server->server_thread_id, NULL, start_event_loop, (void *)server); server_state = env->make_global_ref ( env, env->make_user_ptr (env, free_value, (void *)server)); return server_state; } static emacs_value /* cppcheck-suppress constParameter */ feynman_stop (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) { (void)nargs; (void)data; emacs_value nil = env->intern (env, "nil"); emacs_value first_arg = args[0]; if (env->eq (env, first_arg, nil)) { em_message (env, "server parameter is nil"); return nil; } struct feynman_server *server = (struct feynman_server *)env->get_user_ptr (env, first_arg); stop_feynman (env, server); // deinit_queue(feynman_events_q); emacs_value t = env->intern (env, "t"); return t; } /* Bind NAME to FUN. */ static void bind_function (emacs_env *env, const char *name, emacs_value Sfun) { /* Set the function cell of the symbol named NAME to SFUN using the 'fset' function. */ /* Convert the strings to symbols by interning them */ emacs_value Qfset = env->intern (env, "fset"); emacs_value Qsym = env->intern (env, name); /* Prepare the arguments array */ emacs_value args[] = { Qsym, Sfun }; /* Make the call (2 == nb of arguments) */ env->funcall (env, Qfset, 2, args); } /* Provide FEATURE to Emacs. */ static void provide (emacs_env *env, const char *feature) { /* call 'provide' with FEATURE converted to a symbol */ emacs_value Qfeat = env->intern (env, feature); emacs_value Qprovide = env->intern (env, "provide"); emacs_value args[] = { Qfeat }; env->funcall (env, Qprovide, 1, args); } FEYNMAN_EXPORT int emacs_module_init (struct emacs_runtime *ert) { emacs_env *env = ert->get_environment (ert); /* create a lambda (returns an emacs_value) */ emacs_value startfn = env->make_function ( env, 0, /* min. number of arguments */ 0, /* max. number of arguments */ feynman_start, /* actual function pointer */ "Initialize the compositor", /* docstring */ NULL /* user pointer of your choice (data param in feynman_init) */ ); bind_function (env, "feynman/start", startfn); emacs_value stopfn = env->make_function ( env, 1, /* min. number of arguments */ 1, /* max. number of arguments */ feynman_stop, /* actual function pointer */ "Stop the compositor", /* docstring */ NULL /* user pointer of your choice (data param in feynman_init) */ ); bind_function (env, "feynman/stop", stopfn); provide (env, "feynman"); return 0; }