1 /*
2 * Copyright (C) 2018-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "audio/port.h"
21 #include "audio/port_identifier.h"
22 #include "plugins/plugin_identifier.h"
23 #include "utils/hash.h"
24 #include "utils/objects.h"
25 #include "utils/string.h"
26
27 void
port_identifier_init(PortIdentifier * self)28 port_identifier_init (
29 PortIdentifier * self)
30 {
31 memset (self, 0, sizeof (PortIdentifier));
32 self->schema_version =
33 PORT_IDENTIFIER_SCHEMA_VERSION;
34 plugin_identifier_init (&self->plugin_id);
35 }
36
37 #if 0
38 PortIdentifier *
39 port_identifier_new (void)
40 {
41 PortIdentifier * self =
42 object_new (PortIdentifier);
43 self->schema_version =
44 PORT_IDENTIFIER_SCHEMA_VERSION;
45
46 self->track_pos = -1;
47 plugin_identifier_init (&self->plugin_id);
48
49 return self;
50 }
51 #endif
52
53 /**
54 * Port group comparator function where @ref p1 and
55 * @ref p2 are pointers to Port.
56 */
57 int
port_identifier_port_group_cmp(const void * p1,const void * p2)58 port_identifier_port_group_cmp (
59 const void* p1, const void* p2)
60 {
61 const Port * control1 = *(const Port **)p1;
62 const Port * control2 = *(const Port **)p2;
63
64 g_return_val_if_fail (IS_PORT (control1), -1);
65 g_return_val_if_fail (IS_PORT (control2), -1);
66
67 /* use index for now - this assumes that ports
68 * inside port groups are declared in sequence */
69 return
70 control1->id.port_index -
71 control2->id.port_index;
72
73 #if 0
74 return
75 (control1->id.port_group &&
76 control2->id.port_group) ?
77 strcmp (
78 control1->id.port_group,
79 control2->id.port_group) : 0;
80 #endif
81 }
82
83 /**
84 * Copy the identifier content from \ref src to
85 * \ref dest.
86 *
87 * @note This frees/allocates memory on \ref dest.
88 */
89 void
port_identifier_copy(PortIdentifier * dest,const PortIdentifier * src)90 port_identifier_copy (
91 PortIdentifier * dest,
92 const PortIdentifier * src)
93 {
94 g_return_if_fail (dest != src);
95 dest->schema_version = src->schema_version;
96 string_copy_w_realloc (
97 &dest->label, src->label);
98 string_copy_w_realloc (
99 &dest->sym, src->sym);
100 string_copy_w_realloc (
101 &dest->uri, src->uri);
102 string_copy_w_realloc (
103 &dest->comment, src->comment);
104 dest->owner_type = src->owner_type;
105 dest->type = src->type;
106 dest->flow = src->flow;
107 dest->flags = src->flags;
108 dest->flags2 = src->flags2;
109 plugin_identifier_copy (
110 &dest->plugin_id, &src->plugin_id);
111 string_copy_w_realloc (
112 &dest->ext_port_id, src->ext_port_id);
113 string_copy_w_realloc (
114 &dest->port_group, src->port_group);
115 dest->track_name_hash = src->track_name_hash;
116 dest->port_index = src->port_index;
117 }
118
119 /**
120 * Returns if the 2 PortIdentifier's are equal.
121 */
122 bool
port_identifier_is_equal(const PortIdentifier * src,const PortIdentifier * dest)123 port_identifier_is_equal (
124 const PortIdentifier * src,
125 const PortIdentifier * dest)
126 {
127 bool eq =
128 string_is_equal (dest->label, src->label) &&
129 string_is_equal (dest->uri, src->uri) &&
130 string_is_equal (dest->comment, src->comment) &&
131 dest->owner_type == src->owner_type &&
132 dest->type == src->type &&
133 dest->flow == src->flow &&
134 dest->flags == src->flags &&
135 dest->flags2 == src->flags2 &&
136 dest->track_name_hash == src->track_name_hash &&
137 string_is_equal (
138 dest->port_group, src->port_group) &&
139 string_is_equal (
140 dest->ext_port_id, src->ext_port_id);
141 if (dest->owner_type == PORT_OWNER_TYPE_PLUGIN)
142 {
143 eq =
144 eq &&
145 plugin_identifier_is_equal (
146 &dest->plugin_id, &src->plugin_id);
147 }
148
149 /* if LV2 (has symbol) check symbol match,
150 * otherwise check index match */
151 if (dest->sym)
152 {
153 eq =
154 eq &&
155 string_is_equal (dest->sym, src->sym);
156 }
157 else
158 {
159 eq =
160 eq &&
161 dest->port_index == src->port_index;
162 }
163
164 return eq;
165 }
166
167 /**
168 * To be used as GEqualFunc.
169 */
170 int
port_identifier_is_equal_func(const void * a,const void * b)171 port_identifier_is_equal_func (
172 const void * a,
173 const void * b)
174 {
175 return
176 port_identifier_is_equal (
177 (const PortIdentifier *) a,
178 (const PortIdentifier *) b);
179 }
180
181 void
port_identifier_print_to_str(const PortIdentifier * self,char * buf,size_t buf_sz)182 port_identifier_print_to_str (
183 const PortIdentifier * self,
184 char * buf,
185 size_t buf_sz)
186 {
187 snprintf (
188 buf, buf_sz,
189 "[PortIdentifier %p]\nlabel: %s\n"
190 "sym: %s\nuri: %s\ncomment: %s\nowner type: %s\n"
191 "type: %s\nflow: %s\nflags: %d %d\n"
192 "port group: %s\next port id: %s\n"
193 "track name hash: %u\nport idx: %d",
194 self,
195 self->label, self->sym, self->uri, self->comment,
196 port_owner_type_strings[self->owner_type].str,
197 port_type_strings[self->type].str,
198 port_flow_strings[self->flow].str,
199 self->flags, self->flags2, self->port_group,
200 self->ext_port_id, self->track_name_hash,
201 self->port_index);
202 }
203
204 void
port_identifier_print(const PortIdentifier * self)205 port_identifier_print (
206 const PortIdentifier * self)
207 {
208 size_t size = 2000;
209 char buf[size];
210 port_identifier_print_to_str (self, buf, size);
211 g_message ("%s", buf);
212 }
213
214 bool
port_identifier_validate(PortIdentifier * self)215 port_identifier_validate (
216 PortIdentifier * self)
217 {
218 g_return_val_if_fail (
219 self->schema_version ==
220 PORT_IDENTIFIER_SCHEMA_VERSION &&
221 plugin_identifier_validate (&self->plugin_id),
222 false);
223 return true;
224 }
225
226 unsigned int
port_identifier_get_hash(const void * self)227 port_identifier_get_hash (
228 const void * self)
229 {
230 void * state = hash_create_state ();
231 const PortIdentifier * id =
232 (const PortIdentifier *) self;
233 unsigned int hash = 0;
234 if (id->label)
235 hash = hash ^ g_str_hash (id->label);
236 if (id->sym)
237 hash = hash ^ g_str_hash (id->sym);
238 if (id->uri)
239 hash = hash ^ g_str_hash (id->uri);
240 hash = hash ^ g_int_hash (&id->owner_type);
241 hash = hash ^ g_int_hash (&id->type);
242 hash = hash ^ g_int_hash (&id->flow);
243 hash = hash ^ g_int_hash (&id->flags);
244 hash = hash ^ g_int_hash (&id->flags2);
245 hash = hash ^ g_int_hash (&id->unit);
246 hash =
247 hash ^
248 hash_get_for_struct_full (
249 state, &id->plugin_id,
250 sizeof (PluginIdentifier));
251 if (id->port_group)
252 hash = hash ^ g_str_hash (id->port_group);
253 if (id->ext_port_id)
254 hash = hash ^ g_str_hash (id->ext_port_id);
255 hash = hash ^ id->track_name_hash;
256 hash = hash ^ g_int_hash (&id->port_index);
257 hash_free_state (state);
258 return hash;
259 }
260
261 PortIdentifier *
port_identifier_clone(const PortIdentifier * src)262 port_identifier_clone (
263 const PortIdentifier * src)
264 {
265 PortIdentifier * self =
266 object_new (PortIdentifier);
267 self->schema_version =
268 PORT_IDENTIFIER_SCHEMA_VERSION;
269
270 port_identifier_copy (self, src);
271
272 return self;
273 }
274
275 void
port_identifier_free_members(PortIdentifier * self)276 port_identifier_free_members (
277 PortIdentifier * self)
278 {
279 g_free_and_null (self->label);
280 g_free_and_null (self->sym);
281 g_free_and_null (self->uri);
282 g_free_and_null (self->comment);
283 g_free_and_null (self->port_group);
284 g_free_and_null (self->ext_port_id);
285 object_set_to_zero (self);
286 }
287
288 void
port_identifier_free(PortIdentifier * self)289 port_identifier_free (
290 PortIdentifier * self)
291 {
292 port_identifier_free_members (self);
293 object_zero_and_free (self);
294 }
295
296 void
port_identifier_free_func(void * self)297 port_identifier_free_func (
298 void * self)
299 {
300 port_identifier_free (
301 (PortIdentifier *) self);
302 }
303