1 /*
2 * libInstPatch
3 * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
4 *
5 * Author of this file: (C) 2012 BALATON Zoltan <balaton@eik.bme.hu>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; version 2.1
10 * of the License only.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA or on the web at http://www.gnu.org.
21 */
22 /**
23 * SECTION: IpatchSLIZone
24 * @short_description: Spectralis instrument zone object
25 * @see_also:
26 *
27 * Zones are children of #IpatchSLIInst and define how
28 * their referenced #IpatchSLISample is synthesized.
29 */
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <glib.h>
34 #include <glib-object.h>
35 #include "IpatchSLIZone.h"
36 #include "IpatchSF2GenItem.h"
37 #include "IpatchSample.h"
38 #include "IpatchContainer.h"
39 #include "IpatchTypeProp.h"
40 #include "IpatchRange.h"
41 #include "builtin_enums.h"
42 #include "ipatch_priv.h"
43
44 static void ipatch_sli_zone_sample_iface_init(IpatchSampleIface *sample_iface);
45 static gboolean ipatch_sli_zone_sample_iface_open(IpatchSampleHandle *handle,
46 GError **err);
47 static void ipatch_sli_zone_gen_item_iface_init(IpatchSF2GenItemIface *genitem_iface);
48 static void ipatch_sli_zone_class_init(IpatchSLIZoneClass *klass);
49 static inline void ipatch_sli_zone_get_root_note(IpatchSLIZone *zone,
50 GValue *value);
51 static inline void ipatch_sli_zone_get_fine_tune(IpatchSLIZone *zone,
52 GValue *value);
53 static void ipatch_sli_zone_finalize(GObject *gobject);
54 static void ipatch_sli_zone_get_title(IpatchSLIZone *zone, GValue *value);
55 static void ipatch_sli_zone_set_property(GObject *object, guint property_id,
56 const GValue *value, GParamSpec *pspec);
57 static void ipatch_sli_zone_get_property(GObject *object,
58 guint property_id, GValue *value,
59 GParamSpec *pspec);
60 static void ipatch_sli_zone_item_copy(IpatchItem *dest, IpatchItem *src,
61 IpatchItemCopyLinkFunc link_func,
62 gpointer user_data);
63 static void ipatch_sli_zone_item_remove_full(IpatchItem *item, gboolean full);
64 static void ipatch_sli_zone_real_set_sample(IpatchSLIZone *zone,
65 IpatchSLISample *sample,
66 gboolean sample_notify);
67
68 /* generator property IDs go before these */
69 enum
70 {
71 PROP_TITLE = IPATCH_SF2_GEN_ITEM_FIRST_PROP_USER_ID,
72 PROP_LINK_ITEM,
73 PROP_SAMPLE_SIZE,
74 PROP_SAMPLE_FORMAT,
75 PROP_SAMPLE_RATE,
76 PROP_SAMPLE_DATA,
77 PROP_LOOP_TYPE,
78 PROP_LOOP_START,
79 PROP_LOOP_END,
80 PROP_ROOT_NOTE,
81 PROP_FINE_TUNE
82 };
83
84 /* For quicker access without lookup */
85 static GParamSpec *link_item_pspec;
86 static GParamSpec *root_note_pspec;
87 static GParamSpec *fine_tune_pspec;
88
89 /* For passing data from class init to gen item interface init */
90 static GParamSpec **gen_item_specs = NULL;
91 static GParamSpec **gen_item_setspecs = NULL;
92
G_DEFINE_TYPE_WITH_CODE(IpatchSLIZone,ipatch_sli_zone,IPATCH_TYPE_ITEM,G_IMPLEMENT_INTERFACE (IPATCH_TYPE_SAMPLE,ipatch_sli_zone_sample_iface_init)G_IMPLEMENT_INTERFACE (IPATCH_TYPE_SF2_GEN_ITEM,ipatch_sli_zone_gen_item_iface_init))93 G_DEFINE_TYPE_WITH_CODE(IpatchSLIZone, ipatch_sli_zone, IPATCH_TYPE_ITEM,
94 G_IMPLEMENT_INTERFACE(IPATCH_TYPE_SAMPLE,
95 ipatch_sli_zone_sample_iface_init)
96 G_IMPLEMENT_INTERFACE(IPATCH_TYPE_SF2_GEN_ITEM,
97 ipatch_sli_zone_gen_item_iface_init))
98
99 /* sample interface initialization */
100 static void
101 ipatch_sli_zone_sample_iface_init(IpatchSampleIface *sample_iface)
102 {
103 sample_iface->open = ipatch_sli_zone_sample_iface_open;
104 sample_iface->loop_types = ipatch_sample_loop_types_standard;
105 }
106
107 static gboolean
ipatch_sli_zone_sample_iface_open(IpatchSampleHandle * handle,GError ** err)108 ipatch_sli_zone_sample_iface_open(IpatchSampleHandle *handle, GError **err)
109 {
110 IpatchSLIZone *zone = IPATCH_SLI_ZONE(handle->sample);
111 IpatchSLISample *sample;
112 gboolean retval;
113
114 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
115 g_return_val_if_fail(sample != NULL, FALSE);
116 retval = ipatch_sample_handle_cascade_open(handle, IPATCH_SAMPLE(sample), err);
117 g_object_unref(sample); /* -- unref sample */
118 return (retval);
119 }
120
121 /* gen item interface initialization */
122 static void
ipatch_sli_zone_gen_item_iface_init(IpatchSF2GenItemIface * genitem_iface)123 ipatch_sli_zone_gen_item_iface_init(IpatchSF2GenItemIface *genitem_iface)
124 {
125 genitem_iface->genarray_ofs = G_STRUCT_OFFSET(IpatchSLIZone, genarray);
126 genitem_iface->propstype = IPATCH_SF2_GEN_PROPS_INST;
127
128 g_return_if_fail(gen_item_specs != NULL);
129 g_return_if_fail(gen_item_setspecs != NULL);
130
131 memcpy(&genitem_iface->specs, gen_item_specs, sizeof(genitem_iface->specs));
132 memcpy(&genitem_iface->setspecs, gen_item_setspecs, sizeof(genitem_iface->setspecs));
133 g_free(gen_item_specs);
134 g_free(gen_item_setspecs);
135 }
136
137 static void
ipatch_sli_zone_class_init(IpatchSLIZoneClass * klass)138 ipatch_sli_zone_class_init(IpatchSLIZoneClass *klass)
139 {
140 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
141 IpatchItemClass *item_class = IPATCH_ITEM_CLASS(klass);
142
143 obj_class->finalize = ipatch_sli_zone_finalize;
144 obj_class->get_property = ipatch_sli_zone_get_property;
145
146 item_class->copy = ipatch_sli_zone_item_copy;
147 item_class->item_set_property = ipatch_sli_zone_set_property;
148 item_class->remove_full = ipatch_sli_zone_item_remove_full;
149
150 g_object_class_override_property(obj_class, PROP_TITLE, "title");
151
152 link_item_pspec = g_param_spec_object("link-item", _("Link item"),
153 _("Link item"), IPATCH_TYPE_SLI_SAMPLE,
154 G_PARAM_READWRITE);
155 g_object_class_install_property(obj_class, PROP_LINK_ITEM, link_item_pspec);
156
157 /* properties defined by IpatchSample interface */
158 ipatch_sample_install_property_readonly(obj_class, PROP_SAMPLE_SIZE,
159 "sample-size");
160 ipatch_sample_install_property_readonly(obj_class, PROP_SAMPLE_FORMAT,
161 "sample-format");
162 ipatch_sample_install_property(obj_class, PROP_SAMPLE_RATE, "sample-rate");
163 ipatch_sample_install_property_readonly(obj_class, PROP_SAMPLE_DATA,
164 "sample-data");
165 ipatch_sample_install_property(obj_class, PROP_LOOP_TYPE, "loop-type");
166 ipatch_sample_install_property(obj_class, PROP_LOOP_START, "loop-start");
167 ipatch_sample_install_property(obj_class, PROP_LOOP_END, "loop-end");
168 root_note_pspec = ipatch_sample_install_property(obj_class, PROP_ROOT_NOTE,
169 "root-note");
170 fine_tune_pspec = ipatch_sample_install_property(obj_class, PROP_FINE_TUNE,
171 "fine-tune");
172
173 /* install generator properties */
174 ipatch_sf2_gen_item_iface_install_properties(obj_class,
175 IPATCH_SF2_GEN_PROPS_INST,
176 &gen_item_specs,
177 &gen_item_setspecs);
178 }
179
180 static void
ipatch_sli_zone_init(IpatchSLIZone * zone)181 ipatch_sli_zone_init(IpatchSLIZone *zone)
182 {
183 ipatch_sf2_gen_array_init(&zone->genarray, FALSE, FALSE);
184 }
185
186 static void
ipatch_sli_zone_finalize(GObject * gobject)187 ipatch_sli_zone_finalize(GObject *gobject)
188 {
189 IpatchSLIZone *zone = IPATCH_SLI_ZONE(gobject);
190
191 IPATCH_ITEM_WLOCK(zone);
192
193 if(zone->sample)
194 {
195 g_object_unref(zone->sample);
196 zone->sample = NULL;
197 }
198
199 IPATCH_ITEM_WUNLOCK(zone);
200
201 if(G_OBJECT_CLASS(ipatch_sli_zone_parent_class)->finalize)
202 {
203 G_OBJECT_CLASS(ipatch_sli_zone_parent_class)->finalize(gobject);
204 }
205 }
206
207 static inline void
ipatch_sli_zone_get_root_note(IpatchSLIZone * zone,GValue * value)208 ipatch_sli_zone_get_root_note(IpatchSLIZone *zone, GValue *value)
209 {
210 IpatchSF2GenAmount amount;
211 IpatchSLISample *sample;
212 int val = 0;
213
214 /* root note override not set or -1? - Get sample root note value. */
215 if(!ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
216 IPATCH_SF2_GEN_ROOT_NOTE_OVERRIDE, &amount)
217 || amount.sword == -1)
218 {
219 /* root note override not set, get from sample */
220 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
221
222 if(sample)
223 {
224 g_object_get(sample, "root-note", &val, NULL);
225 g_object_unref(sample); /* -- unref sample */
226 }
227 }
228 else
229 {
230 val = amount.uword;
231 }
232
233 g_value_set_int(value, val);
234 }
235
236 static inline void
ipatch_sli_zone_get_fine_tune(IpatchSLIZone * zone,GValue * value)237 ipatch_sli_zone_get_fine_tune(IpatchSLIZone *zone, GValue *value)
238 {
239 IpatchSF2GenAmount amount;
240 IpatchSLISample *sample;
241 int val = 0;
242
243 /* fine tune override set? */
244 if(!ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
245 IPATCH_SF2_GEN_FINE_TUNE_OVERRIDE, &amount))
246 {
247 /* fine tune override not set, get from sample */
248 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
249
250 if(sample)
251 {
252 g_object_get(sample, "fine-tune", &val, NULL);
253 g_object_unref(sample); /* -- unref sample */
254 }
255 }
256 else
257 {
258 val = amount.sword;
259 }
260
261 g_value_set_int(value, val);
262 }
263
264 static void
ipatch_sli_zone_get_title(IpatchSLIZone * zone,GValue * value)265 ipatch_sli_zone_get_title(IpatchSLIZone *zone, GValue *value)
266 {
267 IpatchSLISample *sample;
268 char *s = NULL;
269
270 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
271
272 if(sample)
273 {
274 g_object_get(sample, "name", &s, NULL);
275 g_object_unref(sample); /* -- unref sample */
276 }
277
278 g_value_take_string(value, s);
279 }
280
281 static void
ipatch_sli_zone_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)282 ipatch_sli_zone_set_property(GObject *object, guint property_id,
283 const GValue *value, GParamSpec *pspec)
284 {
285 IpatchSLIZone *zone = IPATCH_SLI_ZONE(object);
286 IpatchSLISample *sample;
287 IpatchSF2GenAmount amount;
288 GValue vals[2]; /* Gets zeroed below */
289 guint genid;
290 guint uval;
291 int val = 0;
292
293 /* "root-note" and "fine-tune" sample properties get updated for Zone
294 * override property or -set property */
295 if(property_id >= IPATCH_SF2_GEN_ITEM_FIRST_PROP_SET_ID)
296 {
297 genid = property_id - IPATCH_SF2_GEN_ITEM_FIRST_PROP_SET_ID;
298 }
299 else
300 {
301 genid = property_id - IPATCH_SF2_GEN_ITEM_FIRST_PROP_ID;
302 }
303
304 if(genid == IPATCH_SF2_GEN_ROOT_NOTE_OVERRIDE)
305 {
306 memset(vals, 0, sizeof(vals));
307 g_value_init(&vals[0], G_TYPE_INT);
308 ipatch_sli_zone_get_root_note(zone, &vals[0]);
309 }
310 else if(genid == IPATCH_SF2_GEN_FINE_TUNE_OVERRIDE)
311 {
312 memset(vals, 0, sizeof(vals));
313 g_value_init(&vals[0], G_TYPE_INT);
314 ipatch_sli_zone_get_fine_tune(zone, &vals[0]);
315 }
316
317 if(ipatch_sf2_gen_item_iface_set_property((IpatchSF2GenItem *)object,
318 property_id, value))
319 {
320 if(genid == IPATCH_SF2_GEN_ROOT_NOTE_OVERRIDE)
321 {
322 g_value_init(&vals[1], G_TYPE_INT);
323 ipatch_sli_zone_get_root_note(zone, &vals[1]);
324 ipatch_item_prop_notify((IpatchItem *)object, root_note_pspec,
325 &vals[1], &vals[0]);
326 }
327 else if(genid == IPATCH_SF2_GEN_FINE_TUNE_OVERRIDE)
328 {
329 g_value_init(&vals[1], G_TYPE_INT);
330 ipatch_sli_zone_get_fine_tune(zone, &vals[1]);
331 ipatch_item_prop_notify((IpatchItem *)object, fine_tune_pspec,
332 &vals[1], &vals[0]);
333 }
334 }
335 else
336 {
337 switch(property_id)
338 {
339 case PROP_LINK_ITEM:
340 ipatch_sli_zone_real_set_sample(zone, IPATCH_SLI_SAMPLE
341 (g_value_get_object(value)), FALSE);
342 break;
343
344 case PROP_SAMPLE_RATE:
345 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
346
347 if(sample)
348 {
349 g_object_set(sample, "sample-rate", g_value_get_int(value), NULL);
350 g_object_unref(sample); /* -- unref sample */
351 }
352
353 break;
354
355 case PROP_LOOP_TYPE:
356 val = g_value_get_enum(value);
357
358 if(val == IPATCH_SAMPLE_LOOP_NONE)
359 {
360 amount.uword = IPATCH_SF2_GEN_SAMPLE_MODE_NOLOOP;
361 }
362 else
363 {
364 amount.uword = IPATCH_SF2_GEN_SAMPLE_MODE_LOOP;
365 }
366
367 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
368 IPATCH_SF2_GEN_SAMPLE_MODES, &amount);
369 break;
370
371 case PROP_LOOP_START:
372 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
373
374 if(sample)
375 {
376 g_object_get(sample, "loop-start", &uval, NULL);
377 val = g_value_get_uint(value) - uval; /* loop start offset */
378 g_object_unref(sample); /* -- unref sample */
379
380 if(val >= 0)
381 {
382 amount.sword = val >> 15;
383 }
384 else
385 {
386 amount.sword = -(-val >> 15);
387 }
388
389 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
390 IPATCH_SF2_GEN_SAMPLE_COARSE_LOOP_START, &amount);
391
392 if(val >= 0)
393 {
394 amount.sword = val & 0x7FFF;
395 }
396 else
397 {
398 amount.sword = -(-val & 0x7FFF);
399 }
400
401 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
402 IPATCH_SF2_GEN_SAMPLE_LOOP_START, &amount);
403 }
404
405 break;
406
407 case PROP_LOOP_END:
408 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
409
410 if(sample)
411 {
412 g_object_get(sample, "loop-end", &uval, NULL);
413 val = g_value_get_uint(value) - uval; /* loop end offset */
414 g_object_unref(sample); /* -- unref sample */
415
416 if(val >= 0)
417 {
418 amount.sword = val >> 15;
419 }
420 else
421 {
422 amount.sword = -(-val >> 15);
423 }
424
425 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
426 IPATCH_SF2_GEN_SAMPLE_COARSE_LOOP_END, &amount);
427
428 if(val >= 0)
429 {
430 amount.sword = val & 0x7FFF;
431 }
432 else
433 {
434 amount.sword = -(-val & 0x7FFF);
435 }
436
437 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
438 IPATCH_SF2_GEN_SAMPLE_LOOP_END, &amount);
439 }
440
441 break;
442
443 case PROP_ROOT_NOTE:
444 amount.uword = g_value_get_int(value);
445 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
446 IPATCH_SF2_GEN_ROOT_NOTE_OVERRIDE, &amount);
447 break;
448
449 case PROP_FINE_TUNE:
450 amount.sword = g_value_get_int(value);
451 ipatch_sf2_gen_item_set_amount(IPATCH_SF2_GEN_ITEM(zone),
452 IPATCH_SF2_GEN_FINE_TUNE_OVERRIDE, &amount);
453 break;
454
455 default:
456 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
457 return;
458 }
459 }
460 }
461
462 static void
ipatch_sli_zone_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)463 ipatch_sli_zone_get_property(GObject *object, guint property_id,
464 GValue *value, GParamSpec *pspec)
465 {
466 IpatchSLIZone *zone = IPATCH_SLI_ZONE(object);
467 IpatchSLISample *sample;
468 IpatchSF2GenAmount amount;
469 guint uval = 0;
470 int val = 0;
471
472 if(!ipatch_sf2_gen_item_iface_get_property((IpatchSF2GenItem *)object,
473 property_id, value))
474 {
475 switch(property_id)
476 {
477 case PROP_TITLE:
478 ipatch_sli_zone_get_title(zone, value);
479 break;
480
481 case PROP_LINK_ITEM:
482 g_value_take_object(value, ipatch_sli_zone_get_sample(zone));
483 break;
484
485 case PROP_SAMPLE_SIZE:
486 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
487
488 if(sample)
489 {
490 g_object_get_property((GObject *)sample, "sample-size", value);
491 g_object_unref(sample); /* -- unref sample */
492 }
493
494 break;
495
496 case PROP_SAMPLE_FORMAT:
497 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
498
499 if(sample)
500 {
501 g_object_get_property((GObject *)sample, "sample-format", value);
502 g_object_unref(sample); /* -- unref sample */
503 }
504
505 break;
506
507 case PROP_SAMPLE_RATE:
508 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
509
510 if(sample)
511 {
512 g_object_get_property((GObject *)sample, "sample-rate", value);
513 g_object_unref(sample); /* -- unref sample */
514 }
515
516 break;
517
518 case PROP_SAMPLE_DATA:
519 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
520
521 if(sample)
522 {
523 g_object_get_property((GObject *)sample, "sample-data", value);
524 g_object_unref(sample); /* -- unref sample */
525 }
526
527 break;
528
529 case PROP_LOOP_TYPE:
530 ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
531 IPATCH_SF2_GEN_SAMPLE_MODES, &amount);
532
533 if(amount.uword == IPATCH_SF2_GEN_SAMPLE_MODE_NOLOOP)
534 {
535 val = IPATCH_SAMPLE_LOOP_NONE;
536 }
537 else
538 {
539 val = IPATCH_SAMPLE_LOOP_STANDARD;
540 }
541
542 g_value_set_enum(value, val);
543 break;
544
545 case PROP_LOOP_START:
546 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
547
548 if(sample)
549 {
550 g_object_get(sample, "loop-start", &uval, NULL);
551 g_object_unref(sample); /* -- unref sample */
552 val = uval;
553 }
554
555 ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
556 IPATCH_SF2_GEN_SAMPLE_COARSE_LOOP_START,
557 &amount);
558 val += (int)amount.sword << 15;
559
560 ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
561 IPATCH_SF2_GEN_SAMPLE_LOOP_START, &amount);
562 val += amount.sword;
563
564 g_value_set_uint(value, CLAMP(val, 0, G_MAXINT));
565 break;
566
567 case PROP_LOOP_END:
568 sample = ipatch_sli_zone_get_sample(zone); /* ++ ref sample */
569
570 if(sample)
571 {
572 g_object_get(sample, "loop-end", &uval, NULL);
573 g_object_unref(sample); /* -- unref sample */
574 val = uval;
575 }
576
577 ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
578 IPATCH_SF2_GEN_SAMPLE_COARSE_LOOP_END,
579 &amount);
580 val += (int)amount.sword << 15;
581
582 ipatch_sf2_gen_item_get_amount(IPATCH_SF2_GEN_ITEM(zone),
583 IPATCH_SF2_GEN_SAMPLE_LOOP_END, &amount);
584 val += amount.sword;
585
586 g_value_set_uint(value, CLAMP(val, 0, G_MAXINT));
587 break;
588
589 case PROP_ROOT_NOTE:
590 ipatch_sli_zone_get_root_note(zone, value);
591 break;
592
593 case PROP_FINE_TUNE:
594 ipatch_sli_zone_get_fine_tune(zone, value);
595 break;
596
597 default:
598 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
599 return;
600 }
601 }
602 }
603
604 static void
ipatch_sli_zone_item_copy(IpatchItem * dest,IpatchItem * src,IpatchItemCopyLinkFunc link_func,gpointer user_data)605 ipatch_sli_zone_item_copy(IpatchItem *dest, IpatchItem *src,
606 IpatchItemCopyLinkFunc link_func,
607 gpointer user_data)
608 {
609 IpatchSLIZone *src_zone, *dest_zone;
610 IpatchSLISample *refsample;
611
612 src_zone = IPATCH_SLI_ZONE(src);
613 dest_zone = IPATCH_SLI_ZONE(dest);
614
615 IPATCH_ITEM_RLOCK(src_zone);
616
617 /* pass the link to the link handler (if any) */
618 refsample = (IpatchSLISample *)
619 IPATCH_ITEM_COPY_LINK_FUNC(dest,
620 IPATCH_ITEM(src_zone->sample),
621 link_func, user_data);
622
623 if(refsample)
624 {
625 ipatch_sli_zone_set_sample(dest_zone, refsample);
626 }
627
628 /* duplicate generator array */
629 memcpy(&dest_zone->genarray, &src_zone->genarray,
630 sizeof(IpatchSF2GenArray));
631
632 IPATCH_ITEM_RUNLOCK(src_zone);
633 }
634
635 static void
ipatch_sli_zone_item_remove_full(IpatchItem * item,gboolean full)636 ipatch_sli_zone_item_remove_full(IpatchItem *item, gboolean full)
637 {
638 if(full)
639 {
640 ipatch_sli_zone_set_sample(IPATCH_SLI_ZONE(item), NULL);
641 }
642
643 if(IPATCH_ITEM_CLASS(ipatch_sli_zone_parent_class)->remove_full)
644 {
645 IPATCH_ITEM_CLASS(ipatch_sli_zone_parent_class)->remove_full(item, full);
646 }
647 }
648
649 /**
650 * ipatch_sli_zone_new:
651 *
652 * Create a new Spectralis instrument zone object.
653 *
654 * Returns: New Spectralis instrument zone with a reference count of 1. Caller
655 * owns the reference and removing it will destroy the item, unless another
656 * reference is added (if its parented for example).
657 */
658 IpatchSLIZone *
ipatch_sli_zone_new(void)659 ipatch_sli_zone_new(void)
660 {
661 return (IPATCH_SLI_ZONE(g_object_new(IPATCH_TYPE_SLI_ZONE, NULL)));
662 }
663
664 /**
665 * ipatch_sli_zone_first: (skip)
666 * @iter: Patch item iterator containing #IpatchSLIZone items
667 *
668 * Gets the first item in a zone iterator. A convenience
669 * wrapper for ipatch_iter_first().
670 *
671 * Returns: The first zone in @iter or %NULL if empty.
672 */
673 IpatchSLIZone *
ipatch_sli_zone_first(IpatchIter * iter)674 ipatch_sli_zone_first(IpatchIter *iter)
675 {
676 GObject *obj;
677 g_return_val_if_fail(iter != NULL, NULL);
678
679 obj = ipatch_iter_first(iter);
680
681 if(obj)
682 {
683 return (IPATCH_SLI_ZONE(obj));
684 }
685 else
686 {
687 return (NULL);
688 }
689 }
690
691 /**
692 * ipatch_sli_zone_next: (skip)
693 * @iter: Patch item iterator containing #IpatchSLIZone items
694 *
695 * Gets the next item in a zone iterator. A convenience wrapper
696 * for ipatch_iter_next().
697 *
698 * Returns: The next zone in @iter or %NULL if at the end of
699 * the list.
700 */
701 IpatchSLIZone *
ipatch_sli_zone_next(IpatchIter * iter)702 ipatch_sli_zone_next(IpatchIter *iter)
703 {
704 GObject *obj;
705 g_return_val_if_fail(iter != NULL, NULL);
706
707 obj = ipatch_iter_next(iter);
708
709 if(obj)
710 {
711 return (IPATCH_SLI_ZONE(obj));
712 }
713 else
714 {
715 return (NULL);
716 }
717 }
718
719 /**
720 * ipatch_sli_zone_set_sample:
721 * @zone: Zone to set sample of
722 * @sample: Sample to set zone to
723 *
724 * Sets the referenced sample of a zone.
725 */
726 void
ipatch_sli_zone_set_sample(IpatchSLIZone * zone,IpatchSLISample * sample)727 ipatch_sli_zone_set_sample(IpatchSLIZone *zone, IpatchSLISample *sample)
728 {
729 g_return_if_fail(IPATCH_IS_SLI_ZONE(zone));
730 g_return_if_fail(IPATCH_IS_SLI_SAMPLE(sample));
731
732 ipatch_sli_zone_real_set_sample(zone, sample, TRUE);
733 }
734
735 static void
ipatch_sli_zone_real_set_sample(IpatchSLIZone * zone,IpatchSLISample * sample,gboolean sample_notify)736 ipatch_sli_zone_real_set_sample(IpatchSLIZone *zone, IpatchSLISample *sample,
737 gboolean sample_notify)
738 {
739 GValue oldval = { 0 }, newval = { 0 };
740 IpatchSLISample *oldsample;
741
742 if(sample_notify)
743 ipatch_item_get_property_fast((IpatchItem *)zone, link_item_pspec,
744 &oldval);
745
746 if(sample)
747 {
748 g_object_ref(sample); /* ref for zone */
749 }
750
751 IPATCH_ITEM_WLOCK(zone);
752 oldsample = zone->sample;
753 zone->sample = sample;
754 IPATCH_ITEM_WUNLOCK(zone);
755
756 if(oldsample)
757 {
758 g_object_unref(oldsample);
759 }
760
761 if(sample_notify)
762 {
763 g_value_init(&newval, IPATCH_TYPE_SLI_SAMPLE);
764 g_value_set_object(&newval, sample);
765 ipatch_item_prop_notify((IpatchItem *)zone, link_item_pspec,
766 &newval, &oldval);
767 g_value_unset(&oldval);
768 g_value_unset(&newval);
769 }
770
771 /* notify title property change */
772 g_value_init(&newval, G_TYPE_STRING);
773 ipatch_sli_zone_get_title(zone, &newval);
774 ipatch_item_prop_notify((IpatchItem *)zone, ipatch_item_pspec_title,
775 &newval, NULL);
776 g_value_unset(&newval);
777 }
778
779 /**
780 * ipatch_sli_zone_get_sample:
781 * @zone: Zone to get referenced sample from
782 *
783 * Gets the referenced sample from a zone.
784 * The returned item's reference count is incremented and the caller
785 * is responsible for unrefing it with g_object_unref() when
786 * done with it.
787 *
788 * Returns: (transfer full): Zone's referenced sample or %NULL if global zone. Remember to
789 * unreference the item with g_object_unref() when done with it.
790 */
791 IpatchSLISample *
ipatch_sli_zone_get_sample(IpatchSLIZone * zone)792 ipatch_sli_zone_get_sample(IpatchSLIZone *zone)
793 {
794 IpatchSLISample *sample;
795
796 g_return_val_if_fail(IPATCH_IS_SLI_ZONE(zone), NULL);
797
798 IPATCH_ITEM_RLOCK(zone);
799 sample = zone->sample;
800
801 if(sample)
802 {
803 g_object_ref(sample);
804 }
805
806 IPATCH_ITEM_RUNLOCK(zone);
807
808 return sample;
809 }
810
811 /**
812 * ipatch_sli_zone_peek_sample: (skip)
813 * @zone: Zone to get referenced item of
814 *
815 * Like ipatch_sli_zone_get_sample() but does not add a reference to
816 * the returned sample. This function should only be used if a reference
817 * of the returned sample is ensured or only the pointer value is of
818 * interest.
819 *
820 * Returns: Zone's linked sample.
821 * Remember that the item has NOT been referenced.
822 */
823 IpatchSLISample *
ipatch_sli_zone_peek_sample(IpatchSLIZone * zone)824 ipatch_sli_zone_peek_sample(IpatchSLIZone *zone)
825 {
826 g_return_val_if_fail(IPATCH_IS_SLI_ZONE(zone), NULL);
827 return (zone->sample); /* atomic read */
828 }
829