lorid

convert chordpro to pdf
git clone git://git.relim.de/lorid.git
Log | Files | Refs | README | LICENSE

commit 1eeaad2ae0779e34f6a80dc0310f9bd2d6bb2867
parent 5cdcd20adae1254f08388e25d3989462bf4d0823
Author: nibo <nibo@relim.de>
Date:   Fri, 11 Oct 2024 14:26:47 +0200

Implement 'chorus' directive

two new settings:
- default chorus label
- if the chorus should be quoted or not

Diffstat:
Mchordpro.c | 401+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mchordpro.h | 4++++
Mconfig.c | 29++++++++++++++++++++++++-----
Mconfig.h | 10+++++-----
Mtodo | 1+
5 files changed, 333 insertions(+), 112 deletions(-)

diff --git a/chordpro.c b/chordpro.c @@ -1424,6 +1424,14 @@ static struct ChoMetadata *cho_metadata_new(void) return meta; } +static void cho_metadata_free(struct ChoMetadata *meta) +{ + free(meta->name); + free(meta->value); + cho_style_free(meta->style); + free(meta); +} + const char *cho_metadata_get(struct ChoMetadata **metadata, const char *name) { int m; @@ -1611,6 +1619,19 @@ static void cho_chord_free(struct ChoChord *chord) free(chord); } +static struct ChoChord *cho_chord_copy(struct ChoChord *chord) +{ + struct ChoChord *copy = malloc(sizeof(struct ChoChord)); + copy->style = cho_style_duplicate(chord->style); + copy->is_canonical = chord->is_canonical; + copy->qual = chord->qual; + copy->name = strdup(chord->name); + copy->root = chord->root ? strdup(chord->root) : NULL; + copy->ext = chord->ext ? strdup(chord->ext) : NULL; + copy->bass = chord->bass ? strdup(chord->bass) : NULL; + return copy; +} + /* returns how many bytes make up the root; returns 0 if no root was found */ static int cho_chord_root_parse(const char *str, struct ChoChord *chord) { @@ -1825,6 +1846,21 @@ static struct ChoAnnotation *cho_annotation_new(void) return annot; } +static void cho_annotation_free(struct ChoAnnotation *annot) +{ + cho_style_free(annot->style); + free(annot->text); + free(annot); +} + +static struct ChoAnnotation *cho_annotation_copy(struct ChoAnnotation *annot) +{ + struct ChoAnnotation *copy = malloc(sizeof(struct ChoAnnotation)); + copy->style = cho_style_duplicate(annot->style); + copy->text = strdup(annot->text); + return copy; +} + int cho_text_above_count(struct ChoLineItemAbove **text_above) { int i = 0; @@ -1833,26 +1869,27 @@ int cho_text_above_count(struct ChoLineItemAbove **text_above) return i; } -static struct ChoLine *cho_line_new(void) +static void cho_text_above_free(struct ChoLineItemAbove *text_above) { - struct ChoLine *line = malloc(sizeof(struct ChoLine)); - line->text_above = NULL; - line->lyrics = NULL; - line->btype = BT_LINE; - return line; + if (text_above->is_chord) { + cho_chord_free(text_above->u.chord); + } else { + cho_annotation_free(text_above->u.annot); + } + free(text_above); } -static int cho_line_compute_chord_position(struct ChoLine *line, int ly, int te) +static struct ChoLineItemAbove *cho_text_above_copy(struct ChoLineItemAbove *text_above) { - if (ly == 0) - return te; - ly--; - size_t lyrics_len = 0; - while (ly >= 0) { - lyrics_len += strlen(line->lyrics[ly]->text); - ly--; + struct ChoLineItemAbove *copy = malloc(sizeof(struct ChoLineItemAbove)); + copy->position = text_above->position; + copy->is_chord = text_above->is_chord; + if (copy->is_chord) { + copy->u.chord = cho_chord_copy(text_above->u.chord); + } else { + copy->u.annot = cho_annotation_copy(text_above->u.annot); } - return lyrics_len + te; + return copy; } static struct ChoLineItem *cho_line_item_new(void) @@ -1870,6 +1907,14 @@ static void cho_line_item_free(struct ChoLineItem *item) free(item); } +static struct ChoLineItem *cho_line_item_copy(struct ChoLineItem *item) +{ + struct ChoLineItem *copy = malloc(sizeof(struct ChoLineItem)); + copy->style = cho_style_duplicate(item->style); + copy->text = strdup(item->text); + return copy; +} + int cho_line_item_count(struct ChoLineItem **items) { int i = 0; @@ -1878,6 +1923,57 @@ int cho_line_item_count(struct ChoLineItem **items) return i; } +static struct ChoLine *cho_line_new(void) +{ + struct ChoLine *line = malloc(sizeof(struct ChoLine)); + line->text_above = NULL; + line->lyrics = NULL; + line->btype = BT_LINE; + return line; +} + +static void cho_line_free(struct ChoLine *line) +{ + int i; + for (i = 0; line->lyrics[i]; i++) { + cho_line_item_free(line->lyrics[i]); + } + for (i = 0; line->text_above[i]; i++) { + cho_text_above_free(line->text_above[i]); + } + free(line->lyrics); + free(line->text_above); + free(line); +} + +static int cho_line_compute_chord_position(struct ChoLine *line, int ly, int te) +{ + if (ly == 0) + return te; + ly--; + size_t lyrics_len = 0; + while (ly >= 0) { + lyrics_len += strlen(line->lyrics[ly]->text); + ly--; + } + return lyrics_len + te; +} + +static struct ChoLabel *cho_section_label_copy(struct ChoLabel *label) +{ + struct ChoLabel *copy = malloc(sizeof(struct ChoLabel)); + copy->name = strdup(label->name); + copy->style = cho_style_duplicate(label->style); + return copy; +} + +static void cho_section_label_free(struct ChoLabel *label) +{ + free(label->name); + cho_style_free(label->style); + free(label); +} + static struct ChoSection *cho_section_new(void) { struct ChoSection *section = malloc(sizeof(struct ChoSection)); @@ -1887,6 +1983,52 @@ static struct ChoSection *cho_section_new(void) return section; } +static void cho_section_free(struct ChoSection *section) +{ + if (section->label) { + cho_section_label_free(section->label); + } + int i; + for (i = 0; section->lines[i]; i++) { + cho_line_free(section->lines[i]); + } + free(section->lines); + free(section); +} + +static struct ChoSection *cho_section_copy(struct ChoSection *section) +{ + struct ChoSection *copy = malloc(sizeof(struct ChoSection)); + copy->type = section->type; + if (section->label) { + copy->label = cho_section_label_copy(section->label); + } else { + copy->label = NULL; + } + copy->lines = NULL; + int li, c, ly; + for (li = 0; section->lines[li]; li++) { + copy->lines = realloc(copy->lines, (li+1) * sizeof(struct ChoLine *)); + copy->lines[li] = cho_line_new(); + copy->lines[li]->btype = section->lines[li]->btype; + for (c = 0; section->lines[li]->text_above[c]; c++) { + copy->lines[li]->text_above = realloc(copy->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + copy->lines[li]->text_above[c] = cho_text_above_copy(section->lines[li]->text_above[c]); + } + copy->lines[li]->text_above = realloc(copy->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + copy->lines[li]->text_above[c] = NULL; + for (ly = 0; section->lines[li]->lyrics[ly]; ly++) { + copy->lines[li]->lyrics = realloc(copy->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + copy->lines[li]->lyrics[ly] = cho_line_item_copy(section->lines[li]->lyrics[ly]); + } + copy->lines[li]->lyrics = realloc(copy->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + copy->lines[li]->lyrics[ly] = NULL; + } + copy->lines = realloc(copy->lines, (li+1) * sizeof(struct ChoLine *)); + copy->lines[li] = NULL; + return copy; +} + static struct ChoSong *cho_song_new(void) { struct ChoSong *song = malloc(sizeof(struct ChoSong)); @@ -1905,61 +2047,13 @@ int cho_song_count(struct ChoSong **songs) static void cho_song_free(struct ChoSong *song) { - int i = 0; - int k = 0; - int c = 0; - int ly = 0; - while (song->metadata[i] != NULL) { - free(song->metadata[i]->name); - free(song->metadata[i]->value); - if (song->metadata[i]->style) { - cho_style_free(song->metadata[i]->style); - } - free(song->metadata[i]); - i++; + int i; + for (i = 0; song->metadata[i]; i++) { + cho_metadata_free(song->metadata[i]); } free(song->metadata); - i = 0; - while (song->sections[i] != NULL) { - if (song->sections[i]->label) { - free(song->sections[i]->label->name); - cho_style_free(song->sections[i]->label->style); - free(song->sections[i]->label); - } - while (song->sections[i]->lines[k] != NULL) { - while (song->sections[i]->lines[k]->lyrics[ly] != NULL) { - cho_style_free(song->sections[i]->lines[k]->lyrics[ly]->style); - free(song->sections[i]->lines[k]->lyrics[ly]->text); - free(song->sections[i]->lines[k]->lyrics[ly]); - ly++; - } - while (song->sections[i]->lines[k]->text_above[c] != NULL) { - if (song->sections[i]->lines[k]->text_above[c]->is_chord) { - cho_style_free(song->sections[i]->lines[k]->text_above[c]->u.chord->style); - free(song->sections[i]->lines[k]->text_above[c]->u.chord->name); - free(song->sections[i]->lines[k]->text_above[c]->u.chord->root); - free(song->sections[i]->lines[k]->text_above[c]->u.chord->ext); - free(song->sections[i]->lines[k]->text_above[c]->u.chord->bass); - free(song->sections[i]->lines[k]->text_above[c]->u.chord); - } else { - cho_style_free(song->sections[i]->lines[k]->text_above[c]->u.annot->style); - free(song->sections[i]->lines[k]->text_above[c]->u.annot->text); - free(song->sections[i]->lines[k]->text_above[c]->u.annot); - } - free(song->sections[i]->lines[k]->text_above[c]); - c++; - } - free(song->sections[i]->lines[k]->lyrics); - free(song->sections[i]->lines[k]->text_above); - free(song->sections[i]->lines[k]); - ly = 0; - c = 0; - k++; - } - free(song->sections[i]->lines); - free(song->sections[i]); - k = 0; - i++; + for (i = 0; song->sections[i]; i++) { + cho_section_free(song->sections[i]); } free(song->sections); free(song); @@ -2103,14 +2197,12 @@ static struct ChoImage *cho_image_directive_parse(const char *str) { } */ -static char *cho_find_chorus_label_name(struct ChoSection **sections, int se) +static struct ChoSection *cho_find_previous_chorus(struct ChoSection **sections, int se) { int i; for (i = se; i>=0; i--) { if (sections[i]->type == ST_CHORUS) { - if (sections[i]->label) { - return strdup(sections[i]->label->name); - } + return sections[i]; } } return NULL; @@ -2470,6 +2562,7 @@ struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct struct Style *tag_style; struct StyleProperty sprop; struct ChoChord *tmp_chord; + struct ChoSection *chorus; struct ChoImage *image; while (feof(fp) == 0) { read = fread(&buf, 1, 1, fp); @@ -2612,25 +2705,74 @@ struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct break; case POS_EMPTY: /* INFO: {chorus} */ - label = cho_find_chorus_label_name(songs[so]->sections, se); - if (!label) { - label = strdup("Chorus"); - } - songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + chorus = cho_find_previous_chorus(songs[so]->sections, se); + if (chorus) { + if (config->output->chorus->quote) { + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + ly++; + songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = NULL; + ly = 0; + te = 0; + songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + songs[so]->sections[se]->lines[li]->text_above[c] = NULL; + c = 0; + cho_line_free(songs[so]->sections[se]->lines[li]); + // songs[so]->sections[se]->lines = realloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); + songs[so]->sections[se]->lines[li] = NULL; + li = 0; + se++; + songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); + songs[so]->sections[se] = cho_section_copy(chorus); + se++; + songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); + songs[so]->sections[se] = cho_section_new(); + songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *)); + songs[so]->sections[se]->lines[li] = cho_line_new(); + songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + } else { + if (chorus->label) { + label = strdup(chorus->label->name); + } else { + label = strdup(config->output->chorus->label); + } + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { + cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + } else { + ly++; + } + songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); + g_current_ftype = SF_LABEL; + songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default(); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = label; + te += strlen(label); + } } else { - ly++; + if (config->output->chorus->quote) { + cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously."); + } + label = strdup(config->output->chorus->label); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { + cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + } else { + ly++; + } + songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); + g_current_ftype = SF_LABEL; + songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default(); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = label; + te += strlen(label); } - songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); - g_current_ftype = SF_LABEL; - songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default(); - songs[so]->sections[se]->lines[li]->lyrics[ly]->text = label; - te += strlen(label); - cho_log(LOG_INFO, "{chorus} directive in sight."); break; default: cho_log(LOG_ERR, "Invalid position value '%d'.", directive->position); @@ -2790,21 +2932,76 @@ struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct case POS_EMPTY: /* INFO: {chorus: ...} */ label = str_remove_leading_whitespace(directive_value); - songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + chorus = cho_find_previous_chorus(songs[so]->sections, se); + if (chorus) { + if (config->output->chorus->quote) { + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + ly++; + songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = NULL; + ly = 0; + te = 0; + songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + songs[so]->sections[se]->lines[li]->text_above[c] = NULL; + c = 0; + cho_line_free(songs[so]->sections[se]->lines[li]); + // songs[so]->sections[se]->lines = realloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); + songs[so]->sections[se]->lines[li] = NULL; + li = 0; + se++; + songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); + songs[so]->sections[se] = cho_section_copy(chorus); + if (songs[so]->sections[se]->label) { + free(songs[so]->sections[se]->label->name); + songs[so]->sections[se]->label->name = label; + } else { + songs[so]->sections[se]->label = malloc(sizeof(struct ChoLabel)); + g_current_ftype = SF_LABEL; + songs[so]->sections[se]->label->style = cho_style_new_default(); + } + se++; + songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); + songs[so]->sections[se] = cho_section_new(); + songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *)); + songs[so]->sections[se]->lines[li] = cho_line_new(); + songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + } else { + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { + cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + } else { + ly++; + } + songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); + g_current_ftype = SF_LABEL; + songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default(); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = label; + te += strlen(label); + } } else { - ly++; + if (config->output->chorus->quote) { + cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously."); + } + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { + cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + } else { + ly++; + } + songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); + g_current_ftype = SF_LABEL; + songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default(); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = label; + te += strlen(label); } - songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); - g_current_ftype = SF_LABEL; - songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default(); - songs[so]->sections[se]->lines[li]->lyrics[ly]->text = label; - te += strlen(label); - cho_log(LOG_INFO, "{chorus: ...} directive in sight."); break; default: cho_log(LOG_ERR, "Invalid position value '%d'.", directive->position); diff --git a/chordpro.h b/chordpro.h @@ -252,6 +252,10 @@ enum BreakType { BT_EMPTY }; +/* + INFO: Depending on the 'dtype' the other + fields have a meaningful value or not. +*/ struct ChoDirective { enum DirectiveType dtype; enum SectionType stype; diff --git a/config.c b/config.c @@ -297,6 +297,9 @@ static struct Config *config_load_default(void) { struct Config *config = malloc(sizeof(struct Config)); config->output = malloc(sizeof(struct ConfigOutput)); + config->output->chorus = malloc(sizeof(struct ConfigChorus)); + config->output->chorus->label = strdup("Chorus"); + config->output->chorus->quote = false; config->output->system = NS_COMMON; config->output->printable_items = malloc(12 * sizeof(struct PrintableItem *)); config->output->printable_items[0] = config_printable_item_new("title"); @@ -348,12 +351,15 @@ static void config_printable_item_print_as_toml(struct PrintableItem *item) void config_print_default(void) { struct Config *config = config_load_default(); - int i = 0; + printf("[notes]\n\n"); + config_notes_print_as_toml(config->output->system, config->output->notes); printf("[output]\n\n"); printf("system = \"%s\"\n\n", config_naming_system_to_config_string(config->output->system)); - printf("[output.notes]\n\n"); - config_notes_print_as_toml(config->output->system, config->output->notes); + printf("[output.chorus]\n\n"); + printf("label = \"Chorus\"\n"); + printf("quote = false\n\n"); printf("[output.styles]\n\n"); + int i = 0; while (config->output->printable_items[i] != NULL) { config_printable_item_print_as_toml(config->output->printable_items[i]); i++; @@ -575,16 +581,27 @@ struct Config *config_load(const char *filepath) } toml_table_t *output = toml_table_table(table, "output"); if (output) { - toml_table_t *notes; + toml_table_t *notes, *chorus; toml_value_t value; enum NamingSystem system; struct Note **custom_notes; + chorus = toml_table_table(output, "chorus"); + if (chorus) { + value = toml_table_string(chorus, "label"); + if (value.ok) { + free(config->output->chorus->label); + config->output->chorus->label = value.u.s; + } + value = toml_table_bool(chorus, "quote"); + if (value.ok) { + config->output->chorus->quote = value.u.b; + } + } value = toml_table_string(output, "system"); if (value.ok) { system = config_naming_system_parse(value.u.s); if (system == NS_CUSTOM) { notes = toml_table_table(table, "notes"); - // notes = toml_table_table(output, "notes"); if (!notes) { util_log(LOG_ERR, "Custom notes '%s' has no corresponding definition in [notes].", value.u.s); return NULL; @@ -678,6 +695,8 @@ struct Config *config_load(const char *filepath) void config_free(struct Config *config) { int i; + free(config->output->chorus->label); + free(config->output->chorus); for (i = 0; config->output->printable_items[i]; i++) { config_printable_item_free(config->output->printable_items[i]); } diff --git a/config.h b/config.h @@ -36,13 +36,12 @@ enum NoteType { struct ConfigChords { enum NamingSystem system; enum ParseMode mode; - // struct Note **notes; }; -/* struct Config { - struct PrintableItem **printable_items; - struct ConfigChords *chords; -}; */ +struct ConfigChorus { + char *label; + bool quote; +}; struct ConfigParser { struct ConfigChords *chords; @@ -50,6 +49,7 @@ struct ConfigParser { }; struct ConfigOutput { + struct ConfigChorus *chorus; enum NamingSystem system; struct PrintableItem **printable_items; struct Note **notes; diff --git a/todo b/todo @@ -23,3 +23,4 @@ render in two or more columns find better name for PrintableItem, TextAbove consider freeing memory in case of errors decide and then change consistent global variables prefix 'g_' or not +rename functions *_duplicate to *_copy