-
Notifications
You must be signed in to change notification settings - Fork 1
/
setup.cpp
204 lines (182 loc) · 5.67 KB
/
setup.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
* Copyright (c) 2013-2019 amded workers, All rights reserved.
* Terms for redistribution and use can be found in LICENCE.
*/
/**
* @file setup.cpp
* @brief Configurable setup
*
* Amded does not read a configuration file. Instead, its configurable
* parameters are changed via command line options. This file implements
* parameter storage and retrieval. It does not take care of parsing command
* line arguments.
*
* The trail of action looks like this (for the ‘-t’ command line option):
*
* - The parse_options() function in amded.cpp calls bsd_getopt() from
* bsdgetopt.c; when bsd_getopt() processes the argument that contains th
* ‘-t’ option, parse_options() will see the option's "foo=bar" argument.
*
* - Then, parse_options() uses functionality from tag.cpp to split the
* argument into "foo" and "bar" (ie. tag-name and value). It also takes care
* of verifying that "foo" is a supported tag-name, and that "bar" is a
* reasonable value for "foo" (for example: the "year" tag is supported, and
* needs an integer value).
*
* - At this point, part of amded's setup can be changed. Thus, ‘add_tag()’
* from this file is called to put the gived value for the supported ‘tag_id’
* is stored in the ‘newtags’ map.
*
* Setup details:
*
* Defining values for tags:
*
* Amded is able to change tags in audio-files. The ‘-t’ option is the
* driver for that. The tag-name is turned into a numeric value (enum
* tag_id). The value is an instance of the ‘Value’ class (defined in
* value.h and * value.cpp). The values are put into a map in which the
* tag_id value is the key. Thus "-t foo=bar -t foo=baz" sets the value of
* the "foo" that to "baz".
*
* Read-Map:
*
* Some file types support multiple types of tags: For example mp3 files
* may contain ID3V1 (*yuck*), ID3V2 and apetag tags at the same time.
* Values for the same tags in different tag types may differ. Amded
* supports this while reading tags by providing a list of tag types that
* defines the read-priority of tags for a given file.
*
* For example, if the read-map entry for mp3 files looks like this:
*
* "apetag,id3v2"
*
* ...and you try to look up the "artist" tag, which exists in both tags,
* the value from the ‘apetag’ tag-type. If the "album" tag on the other
* hand, only exists in the ‘id3v2’ tag-type, but not in the ‘apetag’
* tag-type, the value is read from ‘id3v2’. Values from the ‘id3v1’
* tag-type would be ignored entirely.
*
* To support this, amded needs two maps: One map defines which tag-types
* are supported by a file-type. And the other one maps file types to a
* vector of tag-types.
*
* The tag-reading procedure (as started by the ‘-m’ and ‘-l’ options) has
* to obey the vector in the second mapping.
*
* Write-Map:
*
* The write-map addresses the same problem as the read-map, but not while
* reading tags, but while writing them to the file. It defines lists of
* file-types to write to a file, that supports more than one tag-type.
*
* To support this, amded needs the map that defines which tag-types are
* supported in a file-type (the same as with the read-map). In addition to
* that, a mapping of file type to a vector of tag-types is needed again.
*
* The tag-writing procedure then writes the tags to _all_ tag-types listed
* in that vector.
*
* Boolean flags:
*
* Amded's behaviour can also be altered by a set of boolean flags (such
* as ‘-E’). The implementation works by setting and reading bits in a
* large integer word.
*/
#include <cstdint>
#include <map>
#include <vector>
#include "amded.h"
#include "setup.h"
#include "value.h"
/*
* Tag value settings:
*/
std::map< enum tag_id, Value > newtags;
void
add_tag(enum tag_id id, const Value &v)
{
newtags[id] = v;
}
/*
* Read-map:
*/
std::map< enum file_type, std::vector< enum tag_impl > > read_map;
/*
* Write-map:
*/
std::map< enum file_type, std::vector< enum tag_impl > > write_map;
/*
* Boolean option implementation:
*/
/**
* Check whether an option is set.
*
* @code
* if (IS_SET(FOO, datastore)) {
* // FOO is set
* } else if (IS_SET(FOO | BAR, datastore)) {
* // FOO *and* BAR are set
* } else if (IS_SET(FOO, datastore) || IS_SET(BAR, datastore)) {
* // FOO *or* bar are set
* }
* @endcode
*
* @param OPT A bitmask to compare against STORE.
* @param STORE The data store to match OPT against.
*
* @return (macro)
*/
#define IS_SET(OPT, STORE) (((STORE) & (OPT)) == (OPT))
/**
* Set an option bit in `STORE'.
*
* @param OPT A bitmask to set in `STORE'.
* @param STORE The data store to set OPT in.
*
* @return (macro)
*/
#define SET_OPT(OPT, STORE) ((STORE) |= (OPT))
/**
* Unset an option bit in `STORE'.
*
* @param OPT A bitmask to unset in STORE.
* @param STORE The data store to unset OPT in.
*
* @return (macro)
*/
#define UNSET_OPT(OPT, STORE) ((STORE) &= ~(OPT))
/**
* Toggle an option bit in `STORE'.
*
* @param OPT A bitmask to toggle in STORE.
* @param STORE The data store to toggle OPT in.
*
* @return (macro)
*/
#define TOGGLE_OPT(OPT, STORE) ((STORE) ^= (OPT))
static uint32_t amded_options;
void
set_opt(uint32_t optmask)
{
SET_OPT(optmask, amded_options);
}
bool
get_opt(uint32_t optmask)
{
return IS_SET(optmask, amded_options);
}
/*
* Tell -d and -t apart. We need to change the behaviour a little if only -d
* options were given.
*/
static bool otd = true;
bool
only_tag_delete(void)
{
return otd;
}
void
unset_only_tag_delete(void)
{
otd = false;
}