Sélectionner une révision Git
lktadm.c 9,34 Kio
#define _POSIX_C_SOURCE 200809L
#define _DEFAULT_SOURCE
#include <lektor/macro.h>
#include <lektor/defines.h>
#include <lektor/cmd.h>
#include <lektor/config.h>
#include <lektor/mkv.h>
#include <lektor/database.h>
#include <lektor/repo.h>
#include <lektor/utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <sys/wait.h>
static noreturn inline void
fail(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
write(2, "\n", 1);
exit(EXIT_FAILURE);
}
/* ----------------- *
* The main function *
* ----------------- */
static sqlite3 *db = NULL;
static char kara_dir[PATH_MAX], db_path[PATH_MAX], mkvpropedit[PATH_MAX], sqlite3_bin[PATH_MAX],
init_script[PATH_MAX], buf[100];
void
open_db(void)
{
if (!database_new(&db))
fail("Failed to init memory db");
if (config_open(db))
fail("Could not load configuration");
if (!database_config_get_text(db, "externals", "mkvpropedit", mkvpropedit, PATH_MAX))
fail("Not found externals->mkvpropedit");
if (!database_config_get_text(db, "externals", "sqlite3", sqlite3_bin, PATH_MAX))
fail("Not found externals->sqlite3");
if (!database_config_get_text(db, "database", "db_path", db_path, PATH_MAX))
fail("Not found database->db_path");
if (!database_config_get_text(db, "database", "kara_dir", kara_dir, PATH_MAX))
fail("Not found database->kara_dir");
if (!database_config_get_text(db, "database", "init_script", init_script, PATH_MAX))
fail("Not found database->init_script");
}
noreturn void
help(void)
{
static const char *help__ =
"USAGE lktadm <COMMAND> [ARGS [...]]:\n"
"\n"
"COMMANDS:\n"
" init the init sub command\n"
" get <id> get the metadata of a kara from kurisu\n"
" download <id> <path> download\n"
" cat <path> display the metadata of a mkv file\n"
" conf prints the default config file to stdout\n"
"\n"
"INIT COMMANDS:\n"
" database write the default empty database\n"
" popualte populate the database from the filesystem\n"
" metadata write metadata to mkv files on the disk using theirs path\n"
" file <path> init the metadata for a single file by its path\n"
"\n";
write(1, help__, strlen(help__));
exit(EXIT_SUCCESS);
}
noreturn void
conf__(struct lkt_cmd_args *args)
{
(void) args;
fprintf(stdout, "%s\n", lkt_default_config_file);
fprintf(stderr, "You may redirect this output to ~/.config/lektor/lektor.ini\n");
exit(EXIT_SUCCESS);
}
noreturn void
cat__(struct lkt_cmd_args *args)
{
int i;
struct kara_metadata data;
for (i = 0; i < args->argc; ++i) {
if (kara_metadata_read(&data, args->argv[i]))
fail("Failed to read metadata of file %s", args->argv[i]);
printf("Kara path: %s\n"
" Song source: %s\n"
" Song title: %s\n"
" Category: %s\n"
" Type: %s (number %d)\n"
" Author: %s\n"
" Language: %s\n",
args->argv[i], data.source_name, data.song_name, data.category,
data.song_type, data.song_number, data.author_name, data.language);
}
exit(EXIT_SUCCESS);
}
noreturn void
init_metadata__(struct lkt_cmd_args *args)
{
(void) args;
open_db();
metadata_set_directory(kara_dir, mkvpropedit);
exit(EXIT_SUCCESS);
}
noreturn void
init_populate__(struct lkt_cmd_args *args)
{
(void) args;
open_db();
database_update(db, kara_dir);
sqlite3_close(db);
exit(EXIT_SUCCESS);
}
noreturn void
init_file__(struct lkt_cmd_args *args)
{
open_db();
int i;
for (i = 0; i < args->argc; ++i)
metadata_set_file((char *) args->argv[i], mkvpropedit);
exit(EXIT_SUCCESS);
}
noreturn void
init_file_prompt__(struct lkt_cmd_args *args)
{
int i, num;
struct kara_metadata data;
for (i = 0; i < args->argc; ++i) {
fprintf(stdout, "Asking for file '%s':\n", args->argv[i]);
if (get_stdin_line(" song_name (TITLE): ", data.song_name, LEKTOR_TAG_MAX))
fail("Input error");
if (get_stdin_line(" source_name (NAME): ", data.source_name, LEKTOR_TAG_MAX))
fail("Input error");
if (get_stdin_line(" category (cdg, vo, ...): ", data.category, LEKTOR_TAG_MAX))
fail("Input error");
if (get_stdin_line(" type (OP, AMV, ...): ", data.song_type, LEKTOR_TAG_MAX))
fail("Input error");
if (get_stdin_line(" language (jp, fr, undefined, ...): ", data.language, LEKTOR_TAG_MAX))
fail("Input error");
if (get_stdin_line(" author_name (Your peudal): ", data.author_name, LEKTOR_TAG_MAX))
fail("Input error");
if (!get_stdin_line(" type's number(1, 2, ...): ", buf, 100))
data.song_number = ((num = atoi(buf)) <= 0) ? 1 : num;
else
fail("Input error");
kara_metadata_write(&data, args->argv[i], mkvpropedit);
fprintf(stdout, "You may name this kara with the following name: '%s - %s%d - %s'\n",
data.source_name, data.song_type, data.song_number, data.song_name);
}
exit(EXIT_SUCCESS);
}
noreturn void
get__(struct lkt_cmd_args *args)
{
struct kara_metadata data;
struct lkt_repo repo;
if (args->argc != 1)
fail("Invalid argument");
int i = atoi(args->argv[0]);
if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net"))
fail("Cound not create repo");
if (repo_get_id(&repo, i, &data))
fail("Cound not download json for kara %d", i);
printf("Kara id: %d\n"
" Song source: %s\n"
" Song title: %s\n"
" Category: %s\n"
" Type: %s (number %d)\n"
" Author: %s\n"
" Language: %s\n",
i, data.source_name, data.song_name, data.category,
data.song_type, data.song_number, data.author_name,
data.language);
exit(EXIT_SUCCESS);
}
noreturn void
init_database__(struct lkt_cmd_args *args)
{
(void) args;
pid_t pid;
int wstatus, status, fd;
open_db();
char *sqlite_args[] = { sqlite3_bin, db_path, NULL };
if ((pid = fork()) == 0) {
if ((fd = open(init_script, O_RDONLY)) < 0)
fail("Can't open %s in O_RDONLY", init_script);
if (dup2(fd, 0) < 0)
fail("Failed to duplicate %s to stdin", init_script);
execvp(sqlite_args[0], sqlite_args);
fail("Failed to execute %s: %s", sqlite3_bin, strerror(errno));
}
else if (pid < 0)
fail("Failed to fork: %s", strerror(errno));
else {
do
if (waitpid(pid, &wstatus, WUNTRACED | WCONTINUED) == -1)
fail("Failed to wait children: %s\n", strerror(errno));
while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
if ((status = WEXITSTATUS(wstatus)))
fail("Children failed with status %d\n", status);
}
exit(EXIT_SUCCESS);
}
noreturn void
download__(struct lkt_cmd_args *args)
{
if (args->argc != 2)
fail("Invalud argument");
struct lkt_repo repo;
struct kara_metadata data;
int i = atoi(args->argv[0]);
if (repo_new(&repo, "kurisu", "https://kurisu.iiens.net"))
fail("Could not create the repo");
if (repo_download_id_sync(&repo, NULL, i, args->argv[1], &data))
fail("Cound not download json for kara %d", i);
printf("Kara %d at %s\n"
" Song source: %s\n"
" Song title: %s\n"
" Category: %s\n"
" Type: %s (number %d)\n"
" Author: %s\n"
" Language: %s\n",
i, args->argv[1], data.source_name, data.song_name, data.category,
data.song_type, data.song_number, data.author_name, data.language);
exit(EXIT_SUCCESS);
}
static struct lkt_cmd_opt options_init[] = {
{ .name = "database", .call = init_database__, .help = "Create an empty database" },
{ .name = "populate", .call = init_populate__, .help = "Populate database from kara on fs" },
{ .name = "metadata", .call = init_metadata__, .help = "Set mdt for all kara in fs" },
{ .name = "file", .call = init_file__, .help = "Set mdt for a kara by its path" },
LKT_OPT_NULL,
};
noreturn void
init__(struct lkt_cmd_args *args)
{
lkt_cmd_parse(options_init, args->argc, args->argv, help);
}
static struct lkt_cmd_opt options[] = {
{ .name = "init", .call = init__, .help = "The init sub-command", .sub = options_init },
{ .name = "get", .call = get__, .help = "Get the mdt of a kara by its id" },
{ .name = "download", .call = download__, .help = "Download a kara by its id" },
{ .name = "cat", .call = cat__, .help = "Prints the mdt of a kara on the fs" },
{ .name = "conf", .call = conf__, .help = "Prints out the default config" },
LKT_OPT_NULL,
};
int
main(int argc, const char **argv)
{
lkt_cmd_help(options, argv[0]);
exit(0);
lkt_cmd_parse(options, argc - 1, argv + 1, help);
}