diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a61fd269acc4e1ecfece7371dba3f5ccc9ef6a8..61cc703840ad672483ca9e0684a97d8105475e27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,15 +228,6 @@ set(lkt_SOURCES src/base/cmd.c ) -set(luka_SOURCES - src/main/luka.c - ${lektor_net_SOURCES} - ${lektor_base_SOURCES} - ${lektor_module_SOURCES} - ${lektor_db_SOURCES} - ${lektor_mkv_SOURCES} -) - set(common_DEFINITIONS LKT_ARCH="${CMAKE_SYSTEM_PROCESSOR}" LKT_MAN_BINARY="${MAN}" @@ -284,12 +275,11 @@ else() ) endif() add_executable(lkt ${lkt_SOURCES}) -add_executable(luka ${luka_SOURCES} ${SQL_GENERATED_FILE}) set(MANPAGES_COMMANDS) if(GENERATE_MANPAGES) message(STATUS "Generating manpages") - set(MANPAGE_COMMANDS lkt lektord lektor luka) + set(MANPAGE_COMMANDS lkt lektord lektor) foreach(CMD IN LISTS MANPAGE_COMMANDS) add_custom_target(manpage_cmd_${CMD} ALL COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/utils/scripts/manpage.bash @@ -313,27 +303,11 @@ target_link_libraries(lektord PRIVATE ${SDL2_IMAGE_LIBRARIES} Qt${QT_VERSION_MAJOR}::Widgets ) -target_link_libraries(luka PRIVATE - ${OpenMP_C_LIBRARIES} - ${MPV_LIBRARY} - ${CMAKE_DL_LIBS} - ${SQLITE3_LIBRARY} - ${SDL2_LIBRARIES} - ${CURL_LIBRARIES} - ${SDL2_IMAGE_LIBRARIES} - Qt${QT_VERSION_MAJOR}::Widgets -) target_link_libraries(lkt PRIVATE ${OpenMP_C_LIBRARIES} ) target_include_directories(lkt PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/inc) -target_include_directories(luka PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/inc - ${SDL2_INCLUDE_DIRS} - ${SDL2_IMAGE_INCLUDE_DIRS} - ${CURL_INCLUDE_DIRS} -) target_include_directories(lektord PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/inc ${SDL2_INCLUDE_DIRS} @@ -343,7 +317,6 @@ target_include_directories(lektord PRIVATE target_compile_definitions(lektord PRIVATE ${common_DEFINITIONS}) target_compile_definitions(lkt PRIVATE ${common_DEFINITIONS}) -target_compile_definitions(luka PRIVATE ${common_DEFINITIONS}) target_compile_options(lektord PRIVATE ${COMMON_C_FLAGS} ${${CMAKE_C_COMPILER_ID}_C_FLAGS} ${${CMAKE_CXX_COMPILER_ID}_CXX_FLAGS}) target_compile_definitions(lektord PRIVATE @@ -354,10 +327,8 @@ target_compile_definitions(lektord PRIVATE ) target_compile_options(lkt PRIVATE ${COMMON_C_FLAGS} ${${CMAKE_C_COMPILER_ID}_C_FLAGS} ${${CMAKE_CXX_COMPILER_ID}_CXX_FLAGS}) -target_compile_options(luka PRIVATE ${COMMON_C_FLAGS} ${${CMAKE_C_COMPILER_ID}_C_FLAGS} ${${CMAKE_CXX_COMPILER_ID}_CXX_FLAGS}) set_property(TARGET lektord PROPERTY CXX_STANDARD 20) -set_property(TARGET luka PROPERTY CXX_STANDARD 20) set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/Rust) @@ -401,10 +372,9 @@ target_link_libraries(lektord # THE INSTALL DIRECTIVES # ### ### -install(TARGETS lektord lkt luka +install(TARGETS lektord lkt RUNTIME # For lektord RUNTIME # For lkt - RUNTIME # For luka ) install(FILES diff --git a/README.md b/README.md index 9dc67192aa4094c7386824357d9da3432a171459..aa1827867f9e553b26ec37aef5ab9bfbae7a4a07 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ The manual way of installing and setting up lektor: ```sh cmake -Bbuild \ -DCMAKE_C_COMPILER=clang \ # Choose the compiler + -DCMAKE_CXX_COMPILER=clang++ \ # Choose the compiler -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ # For clangd/ccls -DCMAKE_BUILD_TYPE=Debug # The debug stuff ``` diff --git a/src/main/luka.c b/src/main/luka.c deleted file mode 100644 index 5a0eb574c34a39c4f29d73d6468af03eca38c1cf..0000000000000000000000000000000000000000 --- a/src/main/luka.c +++ /dev/null @@ -1,472 +0,0 @@ -#include <lektor/common.h> -#include <lektor/cmd.h> -#include <lektor/config.h> -#include <lektor/segv.h> -#include <lektor/commands.h> -#include <lektor/database.h> -#include <lektor/uri.h> -#include <lektor/internal/dbmacro.h> -#include <signal.h> - -/* Static global variables */ - -static struct queue __queue; -static struct lkt_module __mod_repo = MOD_NULL; -static sqlite3 *__db = NULL; - -/* The register */ -REG_DECLARE(repo_reg) -REG_BEGIN(luka_reg) -REG_REGISTER("repo", repo_reg) -REG_END() - -/* Utility functions */ - -DESTRUCTOR_FUNCTION -___cleanup_db(void) -{ - if (__db == NULL) - return; - - static const char *SQL = "UPDATE " LKT_PROTECTED_DATABASE ".misc SET opened = 0;"; - SQLITE_EXEC(__db, SQL, error); - LOG_INFO("DB", "Dec open count on db '" LKT_PROTECTED_DATABASE "'"); - sqlite3_close(__db); - LOG_INFO("DB", "Database was closed successfully"); - __db = NULL; - return; - -error: - LOG_ERROR("DB", "Failed to close database"); - sqlite3_close(__db); - __db = NULL; -} - -DESTRUCTOR_FUNCTION -___cleanup_repo(void) -{ - if (__mod_repo.handle != NULL && __mod_repo.data != NULL && __mod_repo.reg != NULL && - MOD_PROC(__mod_repo, "free")) { - LOG_FATAL("Failed to free module repo"); - } - LOG_INFO("REPO", "Module 'repo' was freed successfully"); -} - -CONSTRUCTOR_FUNCTION -___setup(void) -{ - char path[PATH_MAX]; - memset(path, 0, sizeof(path)); - lkt_queue_new(&__queue); - reg_export(luka_reg); - - FAIL_UNLESS(database_new((lkt_db **)&__db), "Can't init sqlite database"); - FAIL_IF(config_open(__db, path, PATH_MAX), "Failed to read the config"); - - database_config_get_text(__db, "database", "db_path", path, PATH_MAX); - FAIL_UNLESS(database_open(__db, path, true), "Can't open database %s", path); - FAIL_IF(atexit(___cleanup_db), "Failed to register cleanup function"); - LOG_INFO("SETUP", "Setup of database is OK"); - - database_config_get_text(__db, "repo", "module", path, PATH_MAX); - LOG_INFO("SETUP", "Try to import repo module from '%s'", path); - reg_import(path, &__mod_repo.reg, &__mod_repo.handle); - FAIL_IF(MOD_CALL(__mod_repo, "new", &__queue, &__db), "Failed to init repo module %s", path); - LOG_INFO("SETUP", "Setup of repo module is OK"); - - LOG_INFO("SETUP", "Setup phase was successfull"); -} - -/* Private callbacks and internal functions */ - -PRIVATE_FUNCTION EXIT_FUNCTION -___handle_queue_and_exit(void) -{ -#define __CASE(type, func) \ - case LKT_EVENT_##type: \ - if (evt.attr != NULL) { \ - LOG_DEBUG("EVENT", "Got event " #type " (%d) with attr (int: %d, ptr %0*p)", \ - LKT_EVENT_##type, evt.attr, sizeof(size_t) * CHAR_BIT / 4, evt.attr); \ - } else \ - LOG_DEBUG("EVENT", "Got event " #type " (%d) with NULL attr", LKT_EVENT_##type); \ - func; \ - break; - - lkt_event evt; - size_t update_total = 0; - size_t update_current = 0; - bool is_updating = true; - -redo: - if (!is_updating) { - LKT_OUTPUT("GENERAL", "Luka is not updating the database, exiting"); - LKT_OUTPUT("GENERAL", "Total update count is %ld out of %ld", update_current, update_total); - exit(EXIT_SUCCESS); - } - evt = lkt_queue_handle(&__queue); - switch (evt.type) { - // clang-format off - __CASE(DB_UPDATE_TOTAL, { update_total += (size_t)evt.attr; }) - __CASE(DB_UPDATING, { is_updating = (((uint8_t)(size_t)evt.attr) > 0); }) - __CASE(DB_UPDATE_TICK, { - if (update_current != ((size_t)-1)) - update_current++; - if (update_current >= update_total) - (LOG_WARN("EVENT", "Force updating state because tikcs exceded the update count"), - is_updating = false, update_total = 0, update_current = 0); - }) - - __CASE(SKIP_CURRENT, {}) - __CASE(PLAY_FILE, {}) - __CASE(PLAY_POS, {}) - __CASE(PLAY_NEXT, {}) - __CASE(PLAY_PREV, {}) - __CASE(PLAY_TOGGLE, {}) - __CASE(PROP_VOL, {}) - __CASE(PROP_DUR, {}) - __CASE(PROP_TIME, {}) - __CASE(NULL, {}) - - /* Something went REALLY wrong */ - default: - LOG_FATAL("Got unknown type event: %ld", evt.type); - // clang-format on - } - goto redo; - -#undef __ATTR_IS_STATE -#undef __CASE -} - -PRIVATE_FUNCTION bool -___callback_plt_list(struct lkt_state UNUSED *srv, size_t UNUSED c, const char *plt_name) -{ - LKT_OUTPUT("PLT_LIST", "name -> %s", plt_name); - return true; -} - -PRIVATE_FUNCTION bool -___callback_list_row(struct lkt_state UNUSED *srv, size_t UNUSED c, int id, int id_len, - const char *sql_row) -{ - LKT_OUTPUT("SEARCH", "%*d %s", id_len, id, sql_row); - return true; -} - -/* Init database search function */ -typedef bool (*___init_search_function)(lkt_db *, struct lkt_search *); - -PRIVATE_FUNCTION void -___iter_search(___init_search_function init_function, struct lkt_search *search) -{ - size_t continuation = 0, count; - struct lkt_search *new_search = database_search_new_from(search); - -redo_search_for_continuation: - FAIL_UNLESS(init_function((lkt_db *)__db, search), "Failed to init search for database"); - - for (count = 0; database_search_iter(search); ++count) - continue; - - if (count) { - continuation += count; - database_search_set_continuation(new_search, continuation); - search = database_search_new_from(new_search); - goto redo_search_for_continuation; - } - - else - LOG_WARN("COMMAND", "Nothing found"); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -___search(struct cmd_args *args, ___init_search_function init_function) -{ - long count; - struct lkt_uri *search_uri = lkt_uri_new(); - struct lkt_search *search = - database_search_new(NULL, 0, 0, FUNCTION_POINTER(___callback_list_row)); - database_search_set_uri(search, search_uri); - database_search_set_name(search, args->argv[0]); - - FAIL_UNLESS(NULL == args->argv[0], "Invalid argument"); - - FAIL_IF(args->argv[0] && !args->argv[1] && (count = strtol(args->argv[0], NULL, 0)), - "Just an id, use the 'search get' command for that"); - - if (!lkt_uri_from(search_uri, (char **)args->argv)) { - /* Try from idx 1, in case of playlust searches */ - LOG_DEBUG( - "COMMAND", - "URI may not starts at idx 0, may be because of playlist search. At idx 0, value was '%s'", - args->argv[0]); - FAIL_UNLESS(lkt_uri_from(search_uri, (char **)&(args->argv[1])), - "Failed to create the uri"); - } - - database_search_set_uri(search, search_uri); - - ___iter_search(init_function, search); - lkt_uri_free(search_uri); - exit(EXIT_SUCCESS); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__sigpipe(int sig) -{ - LOG_ERROR("GENERAL", "Exit because of signal sigpipe (%d)", sig); - exit(EXIT_FAILURE); -} - -/* Command line functions */ - -PRIVATE_FUNCTION EXIT_FUNCTION __version(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __unref(struct cmd_args *args); - -PRIVATE_FUNCTION EXIT_FUNCTION __admin(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __admin_rescan(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __admin_populate(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __admin_update(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __admin_import(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __admin_config(struct cmd_args *args); - -PRIVATE_FUNCTION EXIT_FUNCTION __search(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __search_database(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __search_plt(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __search_count(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __search_get(struct cmd_args *args); - -PRIVATE_FUNCTION EXIT_FUNCTION __plt(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __plt_delete(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __plt_add(struct cmd_args *args); -PRIVATE_FUNCTION EXIT_FUNCTION __plt_list(struct cmd_args *args); - -// clang-format off -static struct cmd_opt __options_plt[] = { - { "delete", __plt_delete }, - { "add", __plt_add }, - { "list", __plt_list }, - CMD_OPT_NULL, -}; - -static struct cmd_opt __options_search[] = { - { "plt", __search_plt }, - { "count", __search_count }, - { "get", __search_get }, - { "database", __search_database }, - CMD_OPT_DEFAULT(__search_database), -}; - -static struct cmd_opt __options_admin[] = { - { "rescan", __admin_rescan }, - { "populate", __admin_populate }, - { "update", __admin_update }, - { "import", __admin_import }, - { "config", __admin_config }, - CMD_OPT_NULL, -}; - -static struct cmd_opt __options[] = { - { "version", __version }, - { "unref", __unref }, - { "search", __search }, - { "search", __plt }, - { "admin", __admin }, - CMD_OPT_NULL, -}; -// clang-format on - -PRIVATE_FUNCTION EXIT_FUNCTION -__version(struct cmd_args UNUSED *args) -{ - puts("Lektor version " LKT_VERSION); - exit(EXIT_SUCCESS); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__unref(struct cmd_args UNUSED *args) -{ - /* Should be enaugh to clear the inc in the db */ - exit(EXIT_SUCCESS); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__search_database(struct cmd_args *args) -{ - ___search(args, database_search_database_init); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__search_plt(struct cmd_args *args) -{ - ___search(args, database_search_playlist_init); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__search_count(struct cmd_args UNUSED *args) -{ - NOT_IMPLEMENTED; -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__search_get(struct cmd_args *args) -{ - FAIL_UNLESS(args->argc > 1, "Invalid argument"); - struct kara_metadata kara; - char filepath[PATH_MAX]; - long id = strtol(args->argv[0], NULL, 0); - double duration = 0.0; - memset(&kara, 0, sizeof(struct kara_metadata)); - memset(filepath, 0, sizeof(filepath)); - FAIL_UNLESS(database_kara_by_id(__db, (int)id, &kara, filepath), "Failed to find kara %ld", id); - - LKT_OUTPUT("SEARCH", "%s - %s / %s - %s%d - %s [%s]", kara.category, kara.language, - kara.source_name, kara.song_type, kara.song_number, kara.song_name, - kara.author_name); - - /* Print with the duration */ - if (!kara_read_length(&duration, filepath)) { - int s = (int)(duration * 10e-10); - int h = s / 3600; - s = s % 3600; - int m = s / 60; - s = s % 60; - LKT_OUTPUT("SEARCH", "Duration: %d:%02d:%02d", h, m, s); - } - - exit(EXIT_SUCCESS); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__plt_delete(struct cmd_args *args) -{ - FAIL_UNLESS(args->argc < 1, "Invalid number of arguments"); - char *endptr = NULL, err; - long pos; - - if (args->argv[1] == NULL) - exit(!database_plt_remove(__db, args->argv[0])); - - STRTOL(pos, args->argv[1], endptr, err); - FAIL_IF(err, "STRTOL failed"); - exit(!database_plt_remove_pos(__db, args->argv[0], (int)pos)); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__plt_add(struct cmd_args *args) -{ - struct lkt_uri *uri = lkt_uri_new(); - int ret_code = EXIT_FAILURE; - - if (args->argc == 1) - exit(!database_plt_create(__db, args->argv[0])); - - if (!lkt_uri_from(uri, (char *)args->argv[1])) { - LOG_ERROR("COMMAND", "Failed to get uri"); - goto end_plt_add_uri; - } - - else if (!database_plt_add_uri(__db, args->argv[0], uri)) { - LOG_ERROR("COMMAND", "Failed to add uri '%s' to playlist", args->argv[1]); - goto end_plt_add_uri; - } - - ret_code = EXIT_SUCCESS; -end_plt_add_uri: - lkt_uri_free(uri); - exit(ret_code); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__plt_list(struct cmd_args *args) -{ - function_ptr callback = args->argc ? FUNCTION_POINTER(___callback_list_row) - : FUNCTION_POINTER(___callback_plt_list); - struct lkt_uri *null_uri = lkt_uri_new(); - struct lkt_search *search = database_search_new(NULL, 0, 0, callback); - database_search_set_name(search, args->argc ? args->argv[0] : NULL); - database_search_set_uri(search, null_uri); - - ___iter_search(database_search_listplaylist_init, search); - lkt_uri_free(null_uri); - exit(EXIT_SUCCESS); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__admin_rescan(struct cmd_args UNUSED *args) -{ - FAIL_IF(MOD_PROC(__mod_repo, "rescan"), - "Failed to call the 'rescan' function from the repo module"); - ___handle_queue_and_exit(); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__admin_populate(struct cmd_args UNUSED *args) -{ - __admin_rescan(args); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__admin_update(struct cmd_args UNUSED *args) -{ - /* Will need to be copied by the repo module before calling the thread thing */ - struct lkt_uri *null_uri = lkt_uri_new(); - - FAIL_IF(MOD_CALL(__mod_repo, "update", null_uri), - "Failed to call the 'update' function from the repo module"); - lkt_uri_free(null_uri); - ___handle_queue_and_exit(); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__admin_import(struct cmd_args UNUSED *args) -{ - FAIL_IF(MOD_PROC(__mod_repo, "import"), - "Failed to call the 'import' function from the repo module"); - ___handle_queue_and_exit(); -} - -PRIVATE_FUNCTION EXIT_FUNCTION -__admin_config(struct cmd_args UNUSED *args) -{ - fwrite(lkt_default_config_file, sizeof(char), strlen(lkt_default_config_file), stdout); - exit(EXIT_SUCCESS); -} - -/* Sub commands functions */ - -#define __SUB_COMMAND(name) /* Create sub-commands here */ \ - PRIVATE_FUNCTION EXIT_FUNCTION __##name(struct cmd_args *args) \ - { \ - FAIL_IF(args->argc == 0, "Invalid command, specify a sub command for " #name); \ - cmd_parse(__options_##name, args->argc, args->argv); \ - } -__SUB_COMMAND(plt) -__SUB_COMMAND(search) -__SUB_COMMAND(admin) -#undef __SUB_COMMAND - -/* The main function */ - -int -main(const int argc, const char **argv) -{ - cmd_set_executable_name("luka"); - lkt_set_log_level(LOG_LEVEL_ERROR); - lkt_segv_quiet(); - lkt_install_segv_handler(); - - /* 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); - - if (signal(SIGPIPE, __sigpipe)) - LOG_ERROR("SYS", "Failed to install handler for SIGPIPE signal (you may be using php...)"); - - cmd_parse(__options, argc - 1, argv + 1); -}