Sélectionner une révision Git
server.c NaN Gio
#include <lektor/common.h>
#include <lektor/config.h>
#include <lektor/net.h>
#include <lektor/cmd.h>
#include <lektor/reg.h>
#include <lektor/database.h>
#include <lektor/commands.h>
#include <lektor/segv.h>
#include <lektor/launch.h>
#include <lektor/logfile.h>
#include <liblektor-rs/database.h>
#include <wait.h>
#include <spawn.h>
#include <libgen.h>
#include <signal.h>
#include <termios.h>
#if defined(LKT_STATIC_MODULE)
REG_DECLARE(qt_window_reg)
REG_DECLARE(repo_reg)
REG_DECLARE(repo_rs_reg)
#endif
/* TODO: Donesn't work, maybe stdin is no longer valid at the point where that
* function is executed. Use a new function like `lkt_exit` that must be called
* instead of `exit` and do some cleanup there. */
DESTRUCTOR_FUNCTION
___tty_enable_echo(void) { fflush(stdin); }
int
main(int argc, char *argv[])
{
lkt_install_segv_handler();
lkt_thread_set_name("lektord/daemon");
REG_BEGIN(server_reg)
REG_ADD(launch_ext_klkt)
REG_ADD(launch_caching)
REG_ADD(database_upgrade_scheme)
#if defined(LKT_STATIC_MODULE)
REG_REGISTER("repo_rs", repo_rs_reg)
REG_REGISTER("repo", repo_reg)
REG_REGISTER("qt", qt_window_reg)
#endif
REG_END()
/* Enforce some locals */
RETURN_UNLESS(setlocale(LC_ALL, ""), "Failed to set LC_ALL to UTF-8", 1);
RETURN_UNLESS(setlocale(LC_CTYPE, ""), "Failed to set LC_CTYPE", 1);
RETURN_UNLESS(setlocale(LC_NUMERIC, ""), "Failed to set LC_NUMERIC for mpv", 1);
RETURN_UNLESS(STR_MATCH(nl_langinfo(CODESET), "UTF-8"),
"Your locale is not set to an UTF-8 one. "
"Consider using en_US.UTF-8 or fr_FR.UTF-8!",
1);
int autoclear;
int opt;
int check_exclusive = 1;
int dump_and_abort = 0;
char *conf_file = LKT_ALLOC_ARRAY(char, PATH_MAX);
cmd_set_executable_name("lektord");
/* Check args */
while ((opt = getopt(argc, argv, "DhFf:")) != -1) {
switch (opt) {
case 'F': check_exclusive = 0; break;
case 'f': strncpy(conf_file, optarg, PATH_MAX); break;
case 'D': dump_and_abort = 1; break;
case 'h':
default: print_help();
}
}
reg_export(server_reg);
if (lkt_read_self_exe(exe, PATH_MAX))
LOG_WARN("INIT", "Failed to read self executable path, restart may not work");
cmd_set_executable_name(exe);
LOG_WARN("INIT", "The argv[0] from main is: %s", exe);
/* Resolves */
resolve_appimage();
resolve_path();
/* Init the server */
struct lkt_state srv;
memset(&srv, 0, sizeof(struct lkt_state));
srv.kara_prefix = kara_dir;
FAIL_IF(lkt_queue_new(&srv.queue), "Failed to create server queue");
FAIL_UNLESS(database_new(&srv.db), "Failed to init memory database");
FAIL_IF(config_open(srv.db, conf_file, PATH_MAX), "Failed to open or create the config file");
/* Dump and abort here, if we are dumping informations about the server */
if (dump_and_abort) {
fprintf(stderr, "Config file is: %s\n", conf_file);
if (database_config_dump(srv.db, stderr))
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
}
/* No longer need the config file, init the logfile */
free(conf_file);
struct lkt_logfile *logfile = lkt_logfile_new(srv.db);
lkt_set_log_logfile(logfile);
/* Read the configuration. We already know that the config is valid */
database_config_get_int(srv.db, "player", "autoclear", &autoclear);
database_config_get_text(srv.db, "database", "kara_dir", kara_dir, PATH_MAX);
database_config_get_text(srv.db, "server", "host", srv.host, HOST_NAME_MAX);
database_config_get_text(srv.db, "server", "port", srv.port, 5);
/* Quick check with an explicit error message, to remide the users to
* create the kara folder */
FAIL_IF(access(kara_dir, R_OK | W_OK), "No access in read / write for folder %s", kara_dir);
/* Finish to initialize. */
database_config_get_text(srv.db, "database", "db_path", db_path, PATH_MAX);
FAIL_UNLESS(database_open(srv.db, db_path, check_exclusive), "Can't open database");
if (kara_dir[strlen(kara_dir) - 1] != '/')
strncat(kara_dir, "/", PATH_MAX - 1);
srv.kara_prefix = kara_dir;
database_config_queue_default(srv.db);
if (!env_get(LKT_ENV_RESTART) && autoclear) {
LOG_INFO("INIT", "Clear queue, autoclear is set in ini file");
database_queue_clear(srv.db);
}
lkt_queue_make_available(&srv.queue, (LKT_EVENT_TYPE)LKT_EVENT_PROP);
lkt_queue_make_available(&srv.queue, (LKT_EVENT_TYPE)LKT_EVENT_UPDATE);
/* Module initialization */
{
char module[PATH_MAX];
database_config_get_text(srv.db, "player", "module", module, PATH_MAX);
reg_import(module, &srv.window_mod.reg, &srv.window_mod.handle);
database_config_get_text(srv.db, "repo", "module", module, PATH_MAX);
reg_import(module, &srv.repo_mod.reg, &srv.repo_mod.handle);
FAIL_IF(MOD_CALL(srv.repo_mod, "new", &srv.queue, srv.db), "Can't init repo module");
FAIL_IF(MOD_CALL(srv.window_mod, "new", &srv.queue, srv.db), "Can't init player module");
}
/* Get ENV */
{
char *env_current = env_get(LKT_ENV_CURRENT);
if (env_current && env_current[0] && !STR_MATCH(env_current, "NULL")) {
LOG_INFO("INIT", "Restart playback from %s", env_current);
lkt_queue_send(&srv.queue, LKT_EVENT_PLAY_POS,
(void *)(size_t)strtol(env_current, NULL, 0));
}
}
LOG_INFO("INIT", "Lektor was %s", env_get(LKT_ENV_RESTART) ? "restarted" : "started");
config_handle_hook(srv.db, "launched");
lkt_listen(&srv);
LOG_FATAL("The lkt_listen function returned, it shouldn't happen");
return EXIT_FAILURE;
}