-/*
- * Copyright (C) 2008 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2008 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
/** \file afh.c Paraslash's standalone audio format handler tool. */
#include <regex.h>
+#include <lopsub.h>
+#include "afh.lsg.h"
#include "para.h"
#include "string.h"
-#include "afh.cmdline.h"
#include "fd.h"
#include "afh.h"
#include "error.h"
#include "version.h"
-#include "ggo.h"
/** Array of error strings. */
DEFINE_PARA_ERRLIST;
-static struct afh_args_info conf;
+static struct lls_parse_result *lpr;
+
+#define CMD_PTR (lls_cmd(0, afh_suite))
+#define OPT_RESULT(_name) (lls_opt_result(LSG_AFH_PARA_AFH_OPT_ ## _name, lpr))
+#define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name)))
+#define OPT_STRING_VAL(_name) (lls_string_val(0, OPT_RESULT(_name)))
+#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name)))
static int loglevel;
INIT_STDERR_LOGGING(loglevel)
struct taginfo *tags = &afhi->tags;
bool modified = false;
char *tmp_name;
+ const char *arg;
int output_fd = -1, ret;
struct stat sb;
- if (tag_needs_update(conf.year_given, tags->year, conf.year_arg)) {
+ arg = OPT_STRING_VAL(YEAR);
+ if (tag_needs_update(OPT_GIVEN(YEAR), tags->year, arg)) {
free(tags->year);
- tags->year = para_strdup(conf.year_arg);
+ tags->year = para_strdup(arg);
modified = true;
}
- if (tag_needs_update(conf.title_given, tags->title, conf.title_arg)) {
+ arg = OPT_STRING_VAL(TITLE);
+ if (tag_needs_update(OPT_GIVEN(TITLE), tags->title, arg)) {
free(tags->title);
- tags->title = para_strdup(conf.title_arg);
+ tags->title = para_strdup(arg);
modified = true;
}
- if (tag_needs_update(conf.artist_given, tags->artist,
- conf.artist_arg)) {
+ arg = OPT_STRING_VAL(ARTIST);
+ if (tag_needs_update(OPT_GIVEN(ARTIST), tags->artist, arg)) {
free(tags->artist);
- tags->artist = para_strdup(conf.artist_arg);
+ tags->artist = para_strdup(arg);
modified = true;
}
- if (tag_needs_update(conf.album_given, tags->album, conf.album_arg)) {
+ arg = OPT_STRING_VAL(ALBUM);
+ if (tag_needs_update(OPT_GIVEN(ALBUM), tags->album, arg)) {
free(tags->album);
- tags->album = para_strdup(conf.album_arg);
+ tags->album = para_strdup(arg);
modified = true;
}
- if (tag_needs_update(conf.comment_given, tags->comment,
- conf.comment_arg)) {
+ arg = OPT_STRING_VAL(COMMENT);
+ if (tag_needs_update(OPT_GIVEN(COMMENT), tags->comment, arg)) {
free(tags->comment);
- tags->comment = para_strdup(conf.comment_arg);
+ tags->comment = para_strdup(arg);
modified = true;
}
if (!modified) {
tmp_name);
if (ret < 0)
goto out;
- if (conf.backup_given) {
+ if (OPT_GIVEN(BACKUP)) {
char *backup_name = make_message("%s~", name);
ret = xrename(name, backup_name);
free(backup_name);
goto out;
}
ret = xrename(tmp_name, name);
+ if (ret < 0)
+ goto out;
+ if (OPT_GIVEN(PRESERVE)) {
+ struct timespec times[2]; /* [0]: atime, [1]: mtime */
+ times[0].tv_nsec = UTIME_OMIT;
+ times[1] = sb.st_mtim;
+ /*
+ * We might well have written a file of identical size. If we
+ * keep the mtime as well, we might fool backup applications
+ * like rsync which skip files whose size and mtime haven't
+ * changed. So we change the mtime slightly.
+ */
+ times[1].tv_sec++;
+ if (futimens(output_fd, times) < 0) {
+ ret = -ERRNO_TO_PARA_ERROR(errno);
+ goto out;
+ }
+ }
out:
if (ret < 0 && output_fd >= 0)
unlink(tmp_name); /* ignore errors */
struct timeval tv;
long unsigned from, to;
const char *buf;
- size_t len;
+ uint32_t len;
tv_scale(i, &afhi->chunk_tv, &tv);
from = tv2ms(&tv);
tv_scale(i + 1, &afhi->chunk_tv, &tv);
para_strerror(-ret));
return;
}
- if (!conf.parser_friendly_given)
+ if (!OPT_GIVEN(PARSER_FRIENDLY))
printf("%d [%lu.%03lu - %lu.%03lu] ", i, from / 1000,
from % 1000, to / 1000, to % 1000);
printf("%td - %td", buf - (const char *)map,
buf + len - (const char *)map);
- if (!conf.parser_friendly_given)
- printf(" (%zu)", len);
+ if (!OPT_GIVEN(PARSER_FRIENDLY))
+ printf(" (%u)", len);
printf("\n");
}
afh_close(ctx, audio_format_id);
}
-__noreturn static void print_help_and_die(void)
+static void handle_help_flags(void)
{
- struct ggo_help h = DEFINE_GGO_HELP(afh);
- int d = conf.detailed_help_given;
- unsigned flags = d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS;
+ char *help;
- ggo_print_help(&h, flags);
- printf("supported audio formats: %s\n", AUDIO_FORMAT_HANDLERS);
+ if (OPT_GIVEN(DETAILED_HELP))
+ help = lls_long_help(CMD_PTR);
+ else if (OPT_GIVEN(HELP) || lls_num_inputs(lpr) == 0)
+ help = lls_short_help(CMD_PTR);
+ else
+ return;
+ printf("%s", help);
+ free(help);
+ printf("Supported audio formats\n %s\n", AUDIO_FORMAT_HANDLERS);
exit(EXIT_SUCCESS);
}
void *audio_file_data;
size_t audio_file_size;
struct afh_info afhi;
+ char *errctx;
- afh_cmdline_parser(argc, argv, &conf);
- loglevel = get_loglevel_by_name(conf.loglevel_arg);
- version_handle_flag("afh", conf.version_given);
- if (conf.help_given || conf.detailed_help_given || conf.inputs_num == 0)
- print_help_and_die();
- afh_init();
- for (i = 0; i < conf.inputs_num; i++) {
+ ret = lls(lls_parse(argc, argv, CMD_PTR, &lpr, &errctx));
+ if (ret < 0)
+ goto out;
+ loglevel = OPT_UINT32_VAL(LOGLEVEL);
+ version_handle_flag("afh", OPT_GIVEN(VERSION));
+ handle_help_flags();
+ for (i = 0; i < lls_num_inputs(lpr); i++) {
int ret2;
- ret = mmap_full_file(conf.inputs[i], O_RDONLY, &audio_file_data,
+ const char *path = lls_input(i, lpr);
+ ret = mmap_full_file(path, O_RDONLY, &audio_file_data,
&audio_file_size, &fd);
if (ret < 0) {
- PARA_ERROR_LOG("failed to mmap \"%s\"\n", conf.inputs[i]);
+ PARA_ERROR_LOG("failed to mmap \"%s\"\n", path);
goto out;
}
- ret = compute_afhi(conf.inputs[i], audio_file_data, audio_file_size,
+ ret = compute_afhi(path, audio_file_data, audio_file_size,
fd, &afhi);
if (ret >= 0) {
audio_format_num = ret;
- if (conf.modify_given) {
- ret = rewrite_tags(conf.inputs[i], fd, audio_file_data,
+ if (OPT_GIVEN(MODIFY)) {
+ ret = rewrite_tags(path, fd, audio_file_data,
audio_file_size, audio_format_num, &afhi);
} else {
- printf("File %d: %s\n", i + 1, conf.inputs[i]);
+ printf("File %d: %s\n", i + 1, path);
print_info(audio_format_num, &afhi);
- if (conf.chunk_table_given)
+ if (OPT_GIVEN(CHUNK_TABLE))
print_chunk_table(&afhi, audio_format_num,
audio_file_data, audio_file_size);
}
break;
}
out:
+ if (errctx)
+ PARA_ERROR_LOG("%s\n", errctx);
if (ret < 0)
- PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ PARA_EMERG_LOG("%s\n", para_strerror(-ret));
+ lls_free_parse_result(lpr, CMD_PTR);
return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
}