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  * modify it under the terms of the GNU Lesser General 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 Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General 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 #ifndef __IPATCH_ITEM_H__
21 #define __IPATCH_ITEM_H__
22 
23 #include <stdarg.h>
24 #include <glib.h>
25 #include <glib-object.h>
26 
27 typedef struct _IpatchItem IpatchItem;
28 typedef struct _IpatchItemClass IpatchItemClass;
29 
30 #include <libinstpatch/IpatchIter.h>
31 #include <libinstpatch/IpatchList.h>
32 
33 #define IPATCH_TYPE_ITEM   (ipatch_item_get_type ())
34 #define IPATCH_ITEM(obj) \
35   (G_TYPE_CHECK_INSTANCE_CAST ((obj), IPATCH_TYPE_ITEM, IpatchItem))
36 #define IPATCH_ITEM_CLASS(klass) \
37   (G_TYPE_CHECK_CLASS_CAST ((klass), IPATCH_TYPE_ITEM, IpatchItemClass))
38 #define IPATCH_IS_ITEM(obj) \
39   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IPATCH_TYPE_ITEM))
40 #define IPATCH_IS_ITEM_CLASS(klass) \
41   (G_TYPE_CHECK_CLASS_TYPE ((klass), IPATCH_TYPE_ITEM))
42 #define IPATCH_ITEM_GET_CLASS(obj) \
43   (G_TYPE_INSTANCE_GET_CLASS ((obj), IPATCH_TYPE_ITEM, IpatchItemClass))
44 
45 /**
46  * IpatchItemCopyLinkFunc:
47  * @item: Item which is being linked (contains a reference to @link).
48  * @link: The item being referenced (can be NULL).
49  * @user_data: User data supplied to copy/duplicate function.
50  *
51  * A callback function called during item copy/duplicate operations for
52  * any item link reference which needs to be resolved.  An example usage
53  * is for deep duplicating an object (all references can also be duplicated).
54  * Item copy methods should call this for any linked item references which are
55  * not part of the new object.
56  *
57  * Returns: Pointer to item to use for link property (can be the @link item
58  * if the duplicated/copied item is local to the same file).
59  */
60 typedef IpatchItem *(*IpatchItemCopyLinkFunc)(IpatchItem *item,
61         IpatchItem *link,
62         gpointer user_data);
63 
64 /* Base patch item object */
65 struct _IpatchItem
66 {
67     GObject object;
68 
69     /*< private >*/
70 
71     int flags;		/* flag field (atomic int ops used) */
72     IpatchItem *parent;	/* parent item or NULL if not parented or root */
73     IpatchItem *base; 	/* base parent object or NULL */
74     GStaticRecMutex *mutex;  /* pointer to mutex (could be a parent's mutex) */
75 };
76 
77 /* Base patch item class */
78 struct _IpatchItemClass
79 {
80     GObjectClass parent_class;
81 
82     /*< public >*/
83 
84     gboolean mutex_slave;	/* set to TRUE to use parent thread mutex */
85 
86     /* methods */
87     void (*item_set_property)(GObject *object, guint property_id,
88                               const GValue *value, GParamSpec *pspec);
89     void (*copy)(IpatchItem *dest, IpatchItem *src,
90                  IpatchItemCopyLinkFunc link_func, gpointer user_data);
91     void (*remove)(IpatchItem *item);
92 
93     /**
94      * remove_full:
95      * @item: Item to remove references to/from
96      * @full: %TRUE removes all references to and from @item, %FALSE removes only references to @item
97      *
98      * Removes references to/from (depending on the value of @full) @item of other objects in the same
99      * #IpatchBase object.  The remove method can be used instead for default behavior of removing item's
100      * children if it is a container and @full is TRUE.
101      *
102      * Since: 1.1.0
103      */
104     void (*remove_full)(IpatchItem *item, gboolean full);
105 };
106 
107 typedef enum
108 {
109     IPATCH_ITEM_HOOKS_ACTIVE = 1 << 0,  /* hook callbacks active? */
110     IPATCH_ITEM_FREE_MUTEX   = 1 << 1   /* TRUE if item should free its mutex */
111 } IpatchItemFlags;
112 
113 /**
114  * IPATCH_ITEM_UNUSED_FLAG_SHIFT: (skip)
115  */
116 /* 2 flags + reserve 2 bits for future expansion */
117 #define IPATCH_ITEM_UNUSED_FLAG_SHIFT 4
118 
119 /* Multi-thread locking macros. For now there is no distinction between
120    write and read locking since GStaticRWLock is not recursive. */
121 #define IPATCH_ITEM_WLOCK(item)	\
122     g_static_rec_mutex_lock (((IpatchItem *)(item))->mutex)
123 #define IPATCH_ITEM_WUNLOCK(item) \
124     g_static_rec_mutex_unlock (((IpatchItem *)(item))->mutex)
125 #define IPATCH_ITEM_RLOCK(item)		IPATCH_ITEM_WLOCK(item)
126 #define IPATCH_ITEM_RUNLOCK(item)	IPATCH_ITEM_WUNLOCK(item)
127 
128 /**
129  * IpatchItemPropNotify:
130  * @item: Item whose property changed
131  * @pspec: Parameter spec of property which changed
132  * @new_value: New value assigned to the property
133  * @old_value: Old value that the property had (can be %NULL for read only
134  *   properties)
135  * @user_data: User defined pointer from when callback was added
136  * @event_ptrs: Per event data defined by users of callback system
137  *
138  * Property notify information structure.
139  */
140 typedef struct
141 {
142     IpatchItem *item;		/* item whose property changed */
143     GParamSpec *pspec;		/* property spec of the property that changed */
144     const GValue *new_value;	/* new value of the property */
145     const GValue *old_value;	/* old value of the property (can be NULL!) */
146     gpointer user_data;		/* user defined data, defined on connect */
147 
148     /* per event data */
149     struct
150     {
151         gpointer data;		/* implementation defined data per event */
152         GDestroyNotify destroy;	/* function called to cleanup for @data */
153     } eventdata[4];
154 } IpatchItemPropNotify;
155 
156 /**
157  * IPATCH_ITEM_PROP_NOTIFY_SET_EVENT:
158  * @info: IpatchItemPropNotify pointer
159  * @index: Pointer index (0-3)
160  * @data: Data to assign to pointer field
161  * @destroy: Callback function to cleanup @data when done (or %NULL)
162  *
163  * A macro for assigning per event pointers to #IpatchItemPropNotify.
164  */
165 #define IPATCH_ITEM_PROP_NOTIFY_SET_EVENT(info, index, data, destroy) \
166   (info)->eventdata[index].data = data; (info)->eventdata[index].destroy = destroy
167 
168 /**
169  * IpatchItemPropCallback:
170  *
171  * IpatchItem property change callback function prototype.
172  */
173 typedef void (*IpatchItemPropCallback)(IpatchItemPropNotify *notify);
174 
175 /**
176  * IpatchItemPropDisconnect:
177  * @item: Item of prop change match criteria
178  * @pspec: Parameter spec of prop change match criteria
179  * @user_data: User defined pointer from when callback was added
180  *
181  * Function prototype which gets called when a property notify callback gets
182  * disconnected.
183  */
184 typedef void (*IpatchItemPropDisconnect)(IpatchItem *item, GParamSpec *pspec,
185         gpointer user_data);
186 
187 /* Convenience macro used by IpatchItem copy methods to call a copy link
188    function, or use the link pointer directly if function is NULL */
189 #define IPATCH_ITEM_COPY_LINK_FUNC(item, link, func, userdata) \
190   (func ? func (item, link, userdata) : link)
191 
192 /* stored publicy for added convenience to derived types */
193 /* Useful when libinstpatch library is used as a static library. */
194 extern GParamSpec *ipatch_item_pspec_title;
195 
196 /*
197  Getter function returning title property GParamSpec as a convenience to derived type.
198  Useful when libinstpatch library is used as a shared library linked at load time.
199 */
200 GParamSpec *ipatch_item_get_pspec_title(void);
201 
202 GType ipatch_item_get_type(void);
203 int ipatch_item_get_flags(gpointer item);
204 void ipatch_item_set_flags(gpointer item, int flags);
205 void ipatch_item_clear_flags(gpointer item, int flags);
206 void ipatch_item_set_parent(IpatchItem *item, IpatchItem *parent);
207 void ipatch_item_unparent(IpatchItem *item);
208 IpatchItem *ipatch_item_get_parent(IpatchItem *item);
209 IpatchItem *ipatch_item_peek_parent(IpatchItem *item);
210 IpatchItem *ipatch_item_get_base(IpatchItem *item);
211 IpatchItem *ipatch_item_peek_base(IpatchItem *item);
212 IpatchItem *ipatch_item_get_ancestor_by_type(IpatchItem *item,
213         GType ancestor_type);
214 IpatchItem *ipatch_item_peek_ancestor_by_type(IpatchItem *item,
215         GType ancestor_type);
216 void ipatch_item_remove(IpatchItem *item);
217 void ipatch_item_remove_full(IpatchItem *item, gboolean full);
218 void ipatch_item_remove_recursive(IpatchItem *item, gboolean full);
219 void ipatch_item_changed(IpatchItem *item);
220 void ipatch_item_get_property_fast(IpatchItem *item, GParamSpec *pspec,
221                                    GValue *value);
222 void ipatch_item_copy(IpatchItem *dest, IpatchItem *src);
223 void ipatch_item_copy_link_func(IpatchItem *dest, IpatchItem *src,
224                                 IpatchItemCopyLinkFunc link_func,
225                                 gpointer user_data);
226 void ipatch_item_copy_replace(IpatchItem *dest, IpatchItem *src,
227                               GHashTable *repl_hash);
228 IpatchItem *ipatch_item_duplicate(IpatchItem *item);
229 IpatchItem *ipatch_item_duplicate_link_func(IpatchItem *item,
230         IpatchItemCopyLinkFunc link_func,
231         gpointer user_data);
232 IpatchItem *ipatch_item_duplicate_replace(IpatchItem *item,
233         GHashTable *repl_hash);
234 IpatchList *ipatch_item_duplicate_deep(IpatchItem *item);
235 IpatchItem *ipatch_item_copy_link_func_deep(IpatchItem *item, IpatchItem *link,
236         gpointer user_data);
237 IpatchItem *ipatch_item_copy_link_func_hash(IpatchItem *item, IpatchItem *link,
238         gpointer user_data);
239 gboolean ipatch_item_type_can_conflict(GType item_type);
240 GParamSpec **ipatch_item_type_get_unique_specs(GType item_type,
241         guint32 *groups);
242 GValueArray *ipatch_item_get_unique_props(IpatchItem *item);
243 guint ipatch_item_test_conflict(IpatchItem *item1, IpatchItem *item2);
244 void ipatch_item_set_atomic(gpointer item,
245                             const char *first_property_name, ...);
246 void ipatch_item_get_atomic(gpointer item,
247                             const char *first_property_name, ...);
248 IpatchItem *ipatch_item_first(IpatchIter *iter);
249 IpatchItem *ipatch_item_next(IpatchIter *iter);
250 
251 
252 /* in IpatchItemProp.c */
253 
254 
255 void ipatch_item_prop_notify(IpatchItem *item, GParamSpec *pspec,
256                              const GValue *new_value, const GValue *old_value);
257 void ipatch_item_prop_notify_by_name(IpatchItem *item, const char *prop_name,
258                                      const GValue *new_value,
259                                      const GValue *old_value);
260 guint ipatch_item_prop_connect(IpatchItem *item, GParamSpec *pspec,
261                                IpatchItemPropCallback callback,
262                                IpatchItemPropDisconnect disconnect,
263                                gpointer user_data);
264 guint ipatch_item_prop_connect_by_name(IpatchItem *item,
265                                        const char *prop_name,
266                                        IpatchItemPropCallback callback,
267                                        IpatchItemPropDisconnect disconnect,
268                                        gpointer user_data);
269 void ipatch_item_prop_disconnect(guint handler_id);
270 void ipatch_item_prop_disconnect_matched(IpatchItem *item,
271         GParamSpec *pspec,
272         IpatchItemPropCallback callback,
273         gpointer user_data);
274 void ipatch_item_prop_disconnect_by_name(IpatchItem *item,
275         const char *prop_name,
276         IpatchItemPropCallback callback,
277         gpointer user_data);
278 #endif
279