commit f7126d012b878b189d3e5512e8bb9817e21209d4
parent 245ab0fb0ae37601d43bc6deceb5f857fd295f62
Author: nibo <nibo@relim.de>
Date: Tue, 19 Nov 2024 20:55:34 +0100
Improve metadata directive parsing
Diffstat:
3 files changed, 79 insertions(+), 30 deletions(-)
diff --git a/chordpro.c b/chordpro.c
@@ -21,7 +21,7 @@ static const char *environment_directives[] = {
};
static const char *metadata_directives[] = {
- "title", "sorttitle", "subtitle",
+ "title", "t", "subtitle", "st", "sorttitle",
"artist", "composer", "lyricist",
"copyright", "album", "year", "key",
"time", "tempo", "duration", "capo",
@@ -2890,6 +2890,7 @@ cho_directive_new(void)
directive->sprop = SPT_EMPTY;
directive->ftype = SF_EMPTY;
directive->btype = BT_EMPTY;
+ directive->meta = OTHER;
directive->style = cho_style_new_default();
return directive;
}
@@ -3004,6 +3005,33 @@ cho_directive_parse(const char *name)
directive->ftype = SF_TEXT;
goto END;
}
+ if (
+ !strcmp(name, metadata_directives[TITLE]) ||
+ !strcmp(name, metadata_directives[T])
+ ) {
+ directive->dtype = DT_METADATA;
+ directive->meta = TITLE;
+ cho_style_free(directive->style);
+ g_prev_ftype = g_current_ftype;
+ g_current_ftype = SF_TITLE;
+ directive->style = cho_style_new_default();
+ g_current_ftype = g_prev_ftype;
+ goto END;
+
+ } else if (
+ !strcmp(name, metadata_directives[SUBTITLE]) ||
+ !strcmp(name, metadata_directives[ST])
+ ) {
+ directive->dtype = DT_METADATA;
+ directive->meta = SUBTITLE;
+ cho_style_free(directive->style);
+ g_prev_ftype = g_current_ftype;
+ g_current_ftype = SF_SUBTITLE;
+ directive->style = cho_style_new_default();
+ g_current_ftype = g_prev_ftype;
+ goto END;
+ }
+ i = 4;
while (metadata_directives[i] != NULL) {
if (!strcmp(metadata_directives[i], name)) {
directive->dtype = DT_METADATA;
@@ -3289,7 +3317,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
char tag_start[6];
char tag_end[6];
char custom_directive[64];
- char *label;
+ char *label, *metadata_value;
enum State state = STATE_LYRICS;
enum State prev_state = STATE_LYRICS;
int dn = 0;
@@ -3571,12 +3599,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
break;
case DT_METADATA:
- cho_log(LOG_INFO, "Metadata directive '%s' has no value.", directive_name);
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = cho_metadata_new();
- songs[so]->metadata[m]->name = strdup(directive_name);
- m++;
- memset(directive_name, 0, strlen(directive_name));
+ cho_log(LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name);
break;
case DT_FORMATTING:
cho_log(LOG_WARN, "Formatting directive '%s' has no value.", directive_name);
@@ -3828,33 +3851,49 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
break;
case DT_METADATA:
- if (!strcmp(directive_name, "meta")) {
- metadata = cho_metadata_split(directive_value);
- if (metadata) {
+ metadata_value = str_remove_leading_whitespace(directive_value);
+ if (strlen(metadata_value) == 0) {
+ cho_log(LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name);
+ free(metadata_value);
+ break;
+ }
+ switch (directive->meta) {
+ case TITLE:
+ songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
+ songs[so]->metadata[m] = cho_metadata_new();
+ songs[so]->metadata[m]->name = strdup("title");
+ songs[so]->metadata[m]->value = metadata_value;
+ cho_style_free(songs[so]->metadata[m]->style);
+ songs[so]->metadata[m]->style = cho_style_copy(directive->style);
+ m++;
+ break;
+ case SUBTITLE:
+ songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
+ songs[so]->metadata[m] = cho_metadata_new();
+ songs[so]->metadata[m]->name = strdup("subtitle");
+ songs[so]->metadata[m]->value = metadata_value;
+ cho_style_free(songs[so]->metadata[m]->style);
+ songs[so]->metadata[m]->style = cho_style_copy(directive->style);
+ m++;
+ break;
+ default:
+ if (!strcmp(directive_name, "meta")) {
+ metadata = cho_metadata_split(directive_value);
+ if (!metadata) {
+ LOG_DEBUG("cho_metadata_split failed.");
+ return NULL;
+ }
songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
songs[so]->metadata[m] = metadata;
m++;
+ free(metadata_value);
} else {
- LOG_DEBUG("cho_metadata_split failed.");
- return NULL;
- }
- } else {
- songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
- songs[so]->metadata[m] = cho_metadata_new();
- songs[so]->metadata[m]->name = strdup(directive_name);
- songs[so]->metadata[m]->value = str_remove_leading_whitespace(directive_value);
- if (!strcmp(directive_name, "title")) {
- g_prev_ftype = g_current_ftype;
- g_current_ftype = SF_TITLE;
- songs[so]->metadata[m]->style = cho_style_new_default();
- g_current_ftype = g_prev_ftype;
- } else if (!strcmp(directive_name, "subtitle")) {
- g_prev_ftype = g_current_ftype;
- g_current_ftype = SF_SUBTITLE;
- songs[so]->metadata[m]->style = cho_style_new_default();
- g_current_ftype = g_prev_ftype;
+ songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
+ songs[so]->metadata[m] = cho_metadata_new();
+ songs[so]->metadata[m]->name = strdup(directive_name);
+ songs[so]->metadata[m]->value = metadata_value;
+ m++;
}
- m++;
}
break;
case DT_FORMATTING:
diff --git a/chordpro.h b/chordpro.h
@@ -20,6 +20,10 @@ enum EnvironmentDirective {
START_OF_GRID, SOG, END_OF_GRID, EOG
};
+enum MetadataDirective {
+ TITLE, T, SUBTITLE, ST, OTHER
+};
+
enum FormattingDirective {
COMMENT, C, HIGHLIGHT, COMMENT_ITALIC, CI,
COMMENT_BOX, CB
@@ -271,6 +275,7 @@ struct ChoDirective {
enum StylePropertyType sprop;
enum SongFragmentType ftype;
enum BreakType btype;
+ enum MetadataDirective meta;
struct ChoStyle *style;
};
diff --git a/lorid.c b/lorid.c
@@ -70,6 +70,11 @@ main(int argc, char *argv[])
LOG_DEBUG("cho_songs_parse failed.");
return 1;
}
+ struct ChoMetadata **m = songs[0]->metadata;
+ while (*m) {
+ printf("'%s' = '%s'\n", (*m)->name, (*m)->value);
+ m++;
+ }
char *pdf_filename = out_pdf_create(argc == optind+1 ? argv[argc-1] : NULL, output ? output : NULL, songs, config);
if (!pdf_filename) {
LOG_DEBUG("out_pdf_new failed.");