1 /*
2  * libInstPatch
3  * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
4  *
5  * This program is free software; you can redistribute it and/or
6  * connify it under the terms of the GNU Conneral Public License
7  * as published by the Free Software Foundation; version 2.1
8  * of the License only.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Conneral Public License for more details.
14  *
15  * You should have received a copy of the GNU Conneral Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA or on the web at http://www.gnu.org.
19  */
20 /**
21  * SECTION: IpatchDLS2Conn
22  * @short_description: DLS version 2 connection structures and functions
23  * @see_also:
24  * @stability: Stable
25  *
26  * Defines structures and functions used for DLS version 2 instrument
27  * parameters (called connections in DLS terminology).
28  */
29 #include <glib.h>
30 #include <glib-object.h>
31 #include "IpatchDLS2Conn.h"
32 #include "ipatch_priv.h"
33 
34 
35 /**
36  * ipatch_dls2_conn_get_type:
37  *
38  * Get the #IpatchDLS2Conn boxed type
39  *
40  * Returns: Boxed GType of the #IpatchDLS2Conn structure
41  */
42 GType
ipatch_dls2_conn_get_type(void)43 ipatch_dls2_conn_get_type(void)
44 {
45     static GType type = 0;
46 
47     if(!type)
48         type = g_boxed_type_register_static("IpatchDLS2Conn",
49                                             (GBoxedCopyFunc)ipatch_dls2_conn_duplicate,
50                                             (GBoxedFreeFunc)ipatch_dls2_conn_free);
51 
52     return (type);
53 }
54 
55 /**
56  * ipatch_dls2_conn_new: (skip)
57  *
58  * Create a new connection
59  *
60  * Returns: New connection
61  */
62 IpatchDLS2Conn *
ipatch_dls2_conn_new(void)63 ipatch_dls2_conn_new(void)
64 {
65     return (g_slice_new0(IpatchDLS2Conn));
66 }
67 
68 /**
69  * ipatch_dls2_conn_free: (skip)
70  * @conn: Connection to free, should not be referenced by any zones.
71  *
72  * Free an #IpatchDLS2Conn structure
73  */
74 void
ipatch_dls2_conn_free(IpatchDLS2Conn * conn)75 ipatch_dls2_conn_free(IpatchDLS2Conn *conn)
76 {
77     g_slice_free(IpatchDLS2Conn, conn);
78 }
79 
80 /**
81  * ipatch_dls2_conn_duplicate: (skip)
82  * @conn: DLS connection to duplicate
83  *
84  * Duplicate a connection
85  *
86  * Returns: New duplicate connection
87  */
88 IpatchDLS2Conn *
ipatch_dls2_conn_duplicate(const IpatchDLS2Conn * conn)89 ipatch_dls2_conn_duplicate(const IpatchDLS2Conn *conn)
90 {
91     IpatchDLS2Conn *newconn;
92 
93     g_return_val_if_fail(conn != NULL, NULL);
94 
95     newconn = ipatch_dls2_conn_new();
96 
97     newconn->src = conn->src;
98     newconn->ctrlsrc = conn->ctrlsrc;
99     newconn->dest = conn->dest;
100     newconn->trans = conn->trans;
101     newconn->scale = conn->scale;
102 
103     return (newconn);
104 }
105 
106 /**
107  * ipatch_dls2_conn_list_set:
108  * @list: (element-type IpatchDLS2Conn) (transfer none): Pointer to the root pointer of a
109  *   connection list
110  * @conn: DLS connection to set in @list
111  *
112  * Set a connection in a connection list. The connection list is searched for
113  * any existing identical connection (same source, control and destination).
114  * If an identical connection is found, its values are overwritten with the
115  * new values, otherwise a new connection is added to the list and the values
116  * copied to it.
117  */
118 void
ipatch_dls2_conn_list_set(GSList ** list,const IpatchDLS2Conn * conn)119 ipatch_dls2_conn_list_set(GSList **list, const IpatchDLS2Conn *conn)
120 {
121     GSList *p, *last = NULL;
122     IpatchDLS2Conn *c;
123 
124     g_return_if_fail(list != NULL);
125     g_return_if_fail(conn != NULL);
126 
127     p = *list;
128 
129     while(p)
130     {
131         c = (IpatchDLS2Conn *)(p->data);
132 
133         if(IPATCH_DLS2_CONN_ARE_IDENTICAL(c, conn))
134         {
135             break;
136         }
137 
138         last = p;
139         p = g_slist_next(p);
140     }
141 
142     if(!p)			/* duplicate not found? */
143     {
144         c = ipatch_dls2_conn_duplicate(conn);
145 
146         if(last)
147         {
148             last = g_slist_append(last, c);    /* assign to supress gcc warning */
149         }
150         else
151         {
152             *list = g_slist_append(NULL, c);
153         }
154     }
155     else
156     {
157         *c = *conn;    /* overwrite old connection values */
158     }
159 }
160 
161 /**
162  * ipatch_dls2_conn_list_unset:
163  * @list: (element-type IpatchDLS2Conn) (transfer none): Pointer to the root pointer of a
164  *   connection list
165  * @conn: DLS connection to remove from @list
166  *
167  * Remove a connection from a connection list. The connection list is
168  * searched for an identical connection to @conn (same source,
169  * control and destination). If a match is found, it is removed, otherwise
170  * nothing. This essentially sets a connection to its default value, for
171  * those connections which are defined.
172  */
173 void
ipatch_dls2_conn_list_unset(GSList ** list,const IpatchDLS2Conn * conn)174 ipatch_dls2_conn_list_unset(GSList **list, const IpatchDLS2Conn *conn)
175 {
176     IpatchDLS2Conn *c;
177     GSList *p, *prev = NULL;
178 
179     g_return_if_fail(list != NULL);
180     g_return_if_fail(conn != NULL);
181 
182     p = *list;
183 
184     while(p)
185     {
186         c = (IpatchDLS2Conn *)(p->data);
187 
188         if(IPATCH_DLS2_CONN_ARE_IDENTICAL(c, conn))
189         {
190             /* free and remove connection */
191             ipatch_dls2_conn_free(c);
192 
193             if(!prev)
194             {
195                 *list = p->next;
196             }
197             else
198             {
199                 prev->next = p->next;
200             }
201 
202             g_slist_free_1(p);
203             return;
204         }
205 
206         prev = p;
207         p = g_slist_next(p);
208     }
209 }
210 
211 /**
212  * ipatch_dls2_conn_list_duplicate:
213  * @list: (element-type IpatchDLS2Conn) (transfer none): GSList of #IpatchDLS2Conn structures
214  *   to duplicate
215  *
216  * Duplicates a connection list (GSList and connection data).
217  *
218  * Returns: (element-type IpatchDLS2Conn) (transfer full): New duplicate connection list which
219  * should be freed with ipatch_dls2_conn_list_free() when finished with it.
220  */
221 GSList *
ipatch_dls2_conn_list_duplicate(const GSList * list)222 ipatch_dls2_conn_list_duplicate(const GSList *list)
223 {
224     GSList *newlist = NULL;
225 
226     while(list)
227     {
228         newlist = g_slist_prepend(newlist, ipatch_dls2_conn_duplicate
229                                   ((IpatchDLS2Conn *)(list->data)));
230         list = list->next;
231     }
232 
233     return (g_slist_reverse(newlist));
234 }
235 
236 /**
237  * ipatch_dls2_conn_list_duplicate_fast: (skip)
238  * @list: (element-type IpatchDLS2Conn): GSList of #IpatchDLS2Conn structures
239  *   to duplicate
240  *
241  * Like ipatch_dls2_conn_list_duplicate() but optimized for speed, new list
242  * is backwards from original.
243  *
244  * Returns: (element-type IpatchDLS2Conn) (transfer full): New duplicate connection list which
245  *   should be freed with ipatch_dls2_conn_list_free() when finished with it.
246  */
247 GSList *
ipatch_dls2_conn_list_duplicate_fast(const GSList * list)248 ipatch_dls2_conn_list_duplicate_fast(const GSList *list)
249 {
250     GSList *newlist = NULL;
251 
252     while(list)
253     {
254         newlist = g_slist_prepend(newlist, ipatch_dls2_conn_duplicate
255                                   ((IpatchDLS2Conn *)(list->data)));
256         list = list->next;
257     }
258 
259     return (newlist);
260 }
261 
262 /**
263  * ipatch_dls2_conn_list_free: (skip)
264  * @list: (element-type IpatchDLS2Conn): GSList of #IpatchDLS2Conn structures
265  *   to free
266  * @free_conns: If %TRUE then the connections themselves are freed, %FALSE
267  *   makes this function act just like g_slist_free() (only the list is
268  *   freed not the connections).
269  *
270  * Free a list of connections
271  */
272 void
ipatch_dls2_conn_list_free(GSList * list,gboolean free_conns)273 ipatch_dls2_conn_list_free(GSList *list, gboolean free_conns)
274 {
275     GSList *p;
276 
277     if(free_conns)
278     {
279         p = list;
280 
281         while(p)
282         {
283             ipatch_dls2_conn_free((IpatchDLS2Conn *)(p->data));
284             p = g_slist_delete_link(p, p);
285         }
286     }
287     else
288     {
289         g_slist_free(list);
290     }
291 }
292