1 /* GStreamer
2  * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
3  *               2001 Steve Baker <stevebaker_org@yahoo.co.uk>
4  *               2003 Andy Wingo <wingo at pobox.com>
5  *               2016 Stefan Sauer <ensonic@users.sf.net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
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 GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include "gstlv2.h"
27 #include "gstlv2utils.h"
28 
29 #include <string.h>
30 #include <math.h>
31 #include <glib.h>
32 
33 #include <lilv/lilv.h>
34 
35 #include <gst/audio/audio.h>
36 #include <gst/audio/audio-channels.h>
37 #include <gst/base/gstbasesrc.h>
38 
39 GST_DEBUG_CATEGORY_EXTERN (lv2_debug);
40 #define GST_CAT_DEFAULT lv2_debug
41 
42 
43 typedef struct _GstLV2Source GstLV2Source;
44 typedef struct _GstLV2SourceClass GstLV2SourceClass;
45 
46 struct _GstLV2Source
47 {
48   GstBaseSrc parent;
49 
50   GstLV2 lv2;
51 
52   /* audio parameters */
53   GstAudioInfo info;
54   gint samples_per_buffer;
55 
56   /*< private > */
57   gboolean tags_pushed;         /* send tags just once ? */
58   GstClockTimeDiff timestamp_offset;    /* base offset */
59   GstClockTime next_time;       /* next timestamp */
60   gint64 next_sample;           /* next sample to send */
61   gint64 next_byte;             /* next byte to send */
62   gint64 sample_stop;
63   gboolean check_seek_stop;
64   gboolean eos_reached;
65   gint generate_samples_per_buffer;     /* used to generate a partial buffer */
66   gboolean can_activate_pull;
67   gboolean reverse;             /* play backwards */
68 };
69 
70 struct _GstLV2SourceClass
71 {
72   GstBaseSrcClass parent_class;
73 
74   GstLV2Class lv2;
75 };
76 
77 enum
78 {
79   GST_LV2_SOURCE_PROP_0,
80   GST_LV2_SOURCE_PROP_SAMPLES_PER_BUFFER,
81   GST_LV2_SOURCE_PROP_IS_LIVE,
82   GST_LV2_SOURCE_PROP_TIMESTAMP_OFFSET,
83   GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PUSH,
84   GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PULL,
85   GST_LV2_SOURCE_PROP_LAST
86 };
87 
88 static GstBaseSrc *parent_class = NULL;
89 
90 /* preset interface */
91 
92 static gchar **
gst_lv2_source_get_preset_names(GstPreset * preset)93 gst_lv2_source_get_preset_names (GstPreset * preset)
94 {
95   GstLV2Source *self = (GstLV2Source *) preset;
96 
97   return gst_lv2_get_preset_names (&self->lv2, (GstObject *) self);
98 }
99 
100 static gboolean
gst_lv2_source_load_preset(GstPreset * preset,const gchar * name)101 gst_lv2_source_load_preset (GstPreset * preset, const gchar * name)
102 {
103   GstLV2Source *self = (GstLV2Source *) preset;
104 
105   return gst_lv2_load_preset (&self->lv2, (GstObject *) self, name);
106 }
107 
108 static gboolean
gst_lv2_source_save_preset(GstPreset * preset,const gchar * name)109 gst_lv2_source_save_preset (GstPreset * preset, const gchar * name)
110 {
111   GstLV2Source *self = (GstLV2Source *) preset;
112 
113   return gst_lv2_save_preset (&self->lv2, (GstObject *) self, name);
114 }
115 
116 static gboolean
gst_lv2_source_rename_preset(GstPreset * preset,const gchar * old_name,const gchar * new_name)117 gst_lv2_source_rename_preset (GstPreset * preset, const gchar * old_name,
118     const gchar * new_name)
119 {
120   return FALSE;
121 }
122 
123 static gboolean
gst_lv2_source_delete_preset(GstPreset * preset,const gchar * name)124 gst_lv2_source_delete_preset (GstPreset * preset, const gchar * name)
125 {
126   GstLV2Source *self = (GstLV2Source *) preset;
127 
128   return gst_lv2_delete_preset (&self->lv2, (GstObject *) self, name);
129 }
130 
131 static gboolean
gst_lv2_source_set_meta(GstPreset * preset,const gchar * name,const gchar * tag,const gchar * value)132 gst_lv2_source_set_meta (GstPreset * preset, const gchar * name,
133     const gchar * tag, const gchar * value)
134 {
135   return FALSE;
136 }
137 
138 static gboolean
gst_lv2_source_get_meta(GstPreset * preset,const gchar * name,const gchar * tag,gchar ** value)139 gst_lv2_source_get_meta (GstPreset * preset, const gchar * name,
140     const gchar * tag, gchar ** value)
141 {
142   *value = NULL;
143   return FALSE;
144 }
145 
146 static void
gst_lv2_source_preset_interface_init(gpointer g_iface,gpointer iface_data)147 gst_lv2_source_preset_interface_init (gpointer g_iface, gpointer iface_data)
148 {
149   GstPresetInterface *iface = g_iface;
150 
151   iface->get_preset_names = gst_lv2_source_get_preset_names;
152   iface->load_preset = gst_lv2_source_load_preset;
153   iface->save_preset = gst_lv2_source_save_preset;
154   iface->rename_preset = gst_lv2_source_rename_preset;
155   iface->delete_preset = gst_lv2_source_delete_preset;
156   iface->set_meta = gst_lv2_source_set_meta;
157   iface->get_meta = gst_lv2_source_get_meta;
158 }
159 
160 
161 /* GstBasesrc vmethods implementation */
162 
163 static gboolean
gst_lv2_source_set_caps(GstBaseSrc * base,GstCaps * caps)164 gst_lv2_source_set_caps (GstBaseSrc * base, GstCaps * caps)
165 {
166   GstLV2Source *lv2 = (GstLV2Source *) base;
167   GstAudioInfo info;
168 
169   if (!gst_audio_info_from_caps (&info, caps)) {
170     GST_ERROR_OBJECT (base, "received invalid caps");
171     return FALSE;
172   }
173 
174   GST_DEBUG_OBJECT (lv2, "negotiated to caps %" GST_PTR_FORMAT, caps);
175 
176   lv2->info = info;
177 
178   gst_base_src_set_blocksize (base,
179       GST_AUDIO_INFO_BPF (&info) * lv2->samples_per_buffer);
180 
181   if (!gst_lv2_setup (&lv2->lv2, GST_AUDIO_INFO_RATE (&info)))
182     goto no_instance;
183 
184   return TRUE;
185 
186 no_instance:
187   {
188     GST_ERROR_OBJECT (lv2, "could not create instance");
189     return FALSE;
190   }
191 }
192 
193 static GstCaps *
gst_lv2_source_fixate(GstBaseSrc * base,GstCaps * caps)194 gst_lv2_source_fixate (GstBaseSrc * base, GstCaps * caps)
195 {
196   GstLV2Source *lv2 = (GstLV2Source *) base;
197   GstStructure *structure;
198 
199   caps = gst_caps_make_writable (caps);
200 
201   structure = gst_caps_get_structure (caps, 0);
202 
203   GST_DEBUG_OBJECT (lv2, "fixating samplerate to %d", GST_AUDIO_DEF_RATE);
204 
205   gst_structure_fixate_field_nearest_int (structure, "rate",
206       GST_AUDIO_DEF_RATE);
207 
208   gst_structure_fixate_field_string (structure, "format", GST_AUDIO_NE (F32));
209 
210   gst_structure_fixate_field_nearest_int (structure, "channels",
211       lv2->lv2.klass->out_group.ports->len);
212 
213   caps = GST_BASE_SRC_CLASS (parent_class)->fixate (base, caps);
214 
215   return caps;
216 }
217 
218 static void
gst_lv2_source_get_times(GstBaseSrc * base,GstBuffer * buffer,GstClockTime * start,GstClockTime * end)219 gst_lv2_source_get_times (GstBaseSrc * base, GstBuffer * buffer,
220     GstClockTime * start, GstClockTime * end)
221 {
222   /* for live sources, sync on the timestamp of the buffer */
223   if (gst_base_src_is_live (base)) {
224     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
225 
226     if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
227       /* get duration to calculate end time */
228       GstClockTime duration = GST_BUFFER_DURATION (buffer);
229 
230       if (GST_CLOCK_TIME_IS_VALID (duration)) {
231         *end = timestamp + duration;
232       }
233       *start = timestamp;
234     }
235   } else {
236     *start = -1;
237     *end = -1;
238   }
239 }
240 
241 /* seek to time, will be called when we operate in push mode. In pull mode we
242  * get the requested byte offset. */
243 static gboolean
gst_lv2_source_do_seek(GstBaseSrc * base,GstSegment * segment)244 gst_lv2_source_do_seek (GstBaseSrc * base, GstSegment * segment)
245 {
246   GstLV2Source *lv2 = (GstLV2Source *) base;
247   GstClockTime time;
248   gint samplerate, bpf;
249   gint64 next_sample;
250 
251   GST_DEBUG_OBJECT (lv2, "seeking %" GST_SEGMENT_FORMAT, segment);
252 
253   time = segment->position;
254   lv2->reverse = (segment->rate < 0.0);
255 
256   samplerate = GST_AUDIO_INFO_RATE (&lv2->info);
257   bpf = GST_AUDIO_INFO_BPF (&lv2->info);
258 
259   /* now move to the time indicated, don't seek to the sample *after* the time */
260   next_sample = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
261   lv2->next_byte = next_sample * bpf;
262   if (samplerate == 0)
263     lv2->next_time = 0;
264   else
265     lv2->next_time =
266         gst_util_uint64_scale_round (next_sample, GST_SECOND, samplerate);
267 
268   GST_DEBUG_OBJECT (lv2, "seeking next_sample=%" G_GINT64_FORMAT
269       " next_time=%" GST_TIME_FORMAT, next_sample,
270       GST_TIME_ARGS (lv2->next_time));
271 
272   g_assert (lv2->next_time <= time);
273 
274   lv2->next_sample = next_sample;
275 
276   if (!lv2->reverse) {
277     if (GST_CLOCK_TIME_IS_VALID (segment->start)) {
278       segment->time = segment->start;
279     }
280   } else {
281     if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
282       segment->time = segment->stop;
283     }
284   }
285 
286   if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
287     time = segment->stop;
288     lv2->sample_stop =
289         gst_util_uint64_scale_round (time, samplerate, GST_SECOND);
290     lv2->check_seek_stop = TRUE;
291   } else {
292     lv2->check_seek_stop = FALSE;
293   }
294   lv2->eos_reached = FALSE;
295 
296   return TRUE;
297 }
298 
299 static gboolean
gst_lv2_source_is_seekable(GstBaseSrc * base)300 gst_lv2_source_is_seekable (GstBaseSrc * base)
301 {
302   /* we're seekable... */
303   return TRUE;
304 }
305 
306 static gboolean
gst_lv2_source_query(GstBaseSrc * base,GstQuery * query)307 gst_lv2_source_query (GstBaseSrc * base, GstQuery * query)
308 {
309   GstLV2Source *lv2 = (GstLV2Source *) base;
310   gboolean res = FALSE;
311 
312   switch (GST_QUERY_TYPE (query)) {
313     case GST_QUERY_CONVERT:
314     {
315       GstFormat src_fmt, dest_fmt;
316       gint64 src_val, dest_val;
317 
318       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
319 
320       if (!gst_audio_info_convert (&lv2->info, src_fmt, src_val, dest_fmt,
321               &dest_val)) {
322         GST_DEBUG_OBJECT (lv2, "query failed");
323         return FALSE;
324       }
325 
326       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
327       res = TRUE;
328       break;
329     }
330     case GST_QUERY_SCHEDULING:
331     {
332       /* if we can operate in pull mode */
333       gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
334       gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
335       if (lv2->can_activate_pull)
336         gst_query_add_scheduling_mode (query, GST_PAD_MODE_PULL);
337 
338       res = TRUE;
339       break;
340     }
341     default:
342       res = GST_BASE_SRC_CLASS (parent_class)->query (base, query);
343       break;
344   }
345 
346   return res;
347 }
348 
349 static inline void
gst_lv2_source_interleave_data(guint n_channels,gfloat * outdata,guint samples,gfloat * indata)350 gst_lv2_source_interleave_data (guint n_channels, gfloat * outdata,
351     guint samples, gfloat * indata)
352 {
353   guint i, j;
354 
355   for (i = 0; i < n_channels; i++)
356     for (j = 0; j < samples; j++) {
357       outdata[j * n_channels + i] = indata[i * samples + j];
358     }
359 }
360 
361 static GstFlowReturn
gst_lv2_source_fill(GstBaseSrc * base,guint64 offset,guint length,GstBuffer * buffer)362 gst_lv2_source_fill (GstBaseSrc * base, guint64 offset,
363     guint length, GstBuffer * buffer)
364 {
365   GstLV2Source *lv2 = (GstLV2Source *) base;
366   GstLV2SourceClass *klass = (GstLV2SourceClass *) GST_BASE_SRC_GET_CLASS (lv2);
367   GstLV2Class *lv2_class = &klass->lv2;
368   GstLV2Group *lv2_group;
369   GstLV2Port *lv2_port;
370   GstClockTime next_time;
371   gint64 next_sample, next_byte;
372   guint bytes, samples;
373   GstElementClass *eclass;
374   GstMapInfo map;
375   gint samplerate, bpf;
376   guint j, k, l;
377   gfloat *out = NULL, *cv = NULL, *mem;
378   gfloat val;
379 
380   /* example for tagging generated data */
381   if (!lv2->tags_pushed) {
382     GstTagList *taglist;
383 
384     taglist = gst_tag_list_new (GST_TAG_DESCRIPTION, "lv2 wave", NULL);
385 
386     eclass = GST_ELEMENT_CLASS (parent_class);
387     if (eclass->send_event)
388       eclass->send_event (GST_ELEMENT (base), gst_event_new_tag (taglist));
389     else
390       gst_tag_list_unref (taglist);
391     lv2->tags_pushed = TRUE;
392   }
393 
394   if (lv2->eos_reached) {
395     GST_INFO_OBJECT (lv2, "eos");
396     return GST_FLOW_EOS;
397   }
398 
399   samplerate = GST_AUDIO_INFO_RATE (&lv2->info);
400   bpf = GST_AUDIO_INFO_BPF (&lv2->info);
401 
402   /* if no length was given, use our default length in samples otherwise convert
403    * the length in bytes to samples. */
404   if (length == -1)
405     samples = lv2->samples_per_buffer;
406   else
407     samples = length / bpf;
408 
409   /* if no offset was given, use our next logical byte */
410   if (offset == -1)
411     offset = lv2->next_byte;
412 
413   /* now see if we are at the byteoffset we think we are */
414   if (offset != lv2->next_byte) {
415     GST_DEBUG_OBJECT (lv2, "seek to new offset %" G_GUINT64_FORMAT, offset);
416     /* we have a discont in the expected sample offset, do a 'seek' */
417     lv2->next_sample = offset / bpf;
418     lv2->next_time =
419         gst_util_uint64_scale_int (lv2->next_sample, GST_SECOND, samplerate);
420     lv2->next_byte = offset;
421   }
422 
423   /* check for eos */
424   if (lv2->check_seek_stop &&
425       (lv2->sample_stop > lv2->next_sample) &&
426       (lv2->sample_stop < lv2->next_sample + samples)
427       ) {
428     /* calculate only partial buffer */
429     lv2->generate_samples_per_buffer = lv2->sample_stop - lv2->next_sample;
430     next_sample = lv2->sample_stop;
431     lv2->eos_reached = TRUE;
432 
433     GST_INFO_OBJECT (lv2, "eos reached");
434   } else {
435     /* calculate full buffer */
436     lv2->generate_samples_per_buffer = samples;
437     next_sample = lv2->next_sample + (lv2->reverse ? (-samples) : samples);
438   }
439 
440   bytes = lv2->generate_samples_per_buffer * bpf;
441 
442   next_byte = lv2->next_byte + (lv2->reverse ? (-bytes) : bytes);
443   next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
444 
445   GST_LOG_OBJECT (lv2, "samplerate %d", samplerate);
446   GST_LOG_OBJECT (lv2,
447       "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT, next_sample,
448       GST_TIME_ARGS (next_time));
449 
450   gst_buffer_set_size (buffer, bytes);
451 
452   GST_BUFFER_OFFSET (buffer) = lv2->next_sample;
453   GST_BUFFER_OFFSET_END (buffer) = next_sample;
454   if (!lv2->reverse) {
455     GST_BUFFER_TIMESTAMP (buffer) = lv2->timestamp_offset + lv2->next_time;
456     GST_BUFFER_DURATION (buffer) = next_time - lv2->next_time;
457   } else {
458     GST_BUFFER_TIMESTAMP (buffer) = lv2->timestamp_offset + next_time;
459     GST_BUFFER_DURATION (buffer) = lv2->next_time - next_time;
460   }
461 
462   gst_object_sync_values (GST_OBJECT (lv2), GST_BUFFER_TIMESTAMP (buffer));
463 
464   lv2->next_time = next_time;
465   lv2->next_sample = next_sample;
466   lv2->next_byte = next_byte;
467 
468   GST_LOG_OBJECT (lv2, "generating %u samples at ts %" GST_TIME_FORMAT,
469       samples, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
470 
471   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
472 
473   /* multi channel outputs */
474   lv2_group = &lv2_class->out_group;
475   if (lv2_group->ports->len > 1) {
476     out = g_new0 (gfloat, samples * lv2_group->ports->len);
477     for (j = 0; j < lv2_group->ports->len; ++j) {
478       lv2_port = &g_array_index (lv2_group->ports, GstLV2Port, j);
479       lilv_instance_connect_port (lv2->lv2.instance, lv2_port->index,
480           out + (j * samples));
481       GST_LOG_OBJECT (lv2, "connected port %d/%d", j, lv2_group->ports->len);
482     }
483   } else {
484     lv2_port = &g_array_index (lv2_group->ports, GstLV2Port, 0);
485     lilv_instance_connect_port (lv2->lv2.instance, lv2_port->index,
486         (gfloat *) map.data);
487     GST_LOG_OBJECT (lv2, "connected port 0");
488   }
489 
490   /* cv ports */
491   cv = g_new (gfloat, samples * lv2_class->num_cv_in);
492   for (j = k = 0; j < lv2_class->control_in_ports->len; j++) {
493     lv2_port = &g_array_index (lv2_class->control_in_ports, GstLV2Port, j);
494     if (lv2_port->type != GST_LV2_PORT_CV)
495       continue;
496 
497     mem = cv + (k * samples);
498     val = lv2->lv2.ports.control.in[j];
499     /* FIXME: use gst_control_binding_get_value_array */
500     for (l = 0; l < samples; l++)
501       mem[l] = val;
502     lilv_instance_connect_port (lv2->lv2.instance, lv2_port->index, mem);
503     k++;
504   }
505 
506   lilv_instance_run (lv2->lv2.instance, samples);
507 
508   if (lv2_group->ports->len > 1) {
509     gst_lv2_source_interleave_data (lv2_group->ports->len,
510         (gfloat *) map.data, samples, out);
511     g_free (out);
512   }
513 
514   g_free (cv);
515 
516   gst_buffer_unmap (buffer, &map);
517 
518   return GST_FLOW_OK;
519 }
520 
521 static gboolean
gst_lv2_source_start(GstBaseSrc * base)522 gst_lv2_source_start (GstBaseSrc * base)
523 {
524   GstLV2Source *lv2 = (GstLV2Source *) base;
525 
526   lv2->next_sample = 0;
527   lv2->next_byte = 0;
528   lv2->next_time = 0;
529   lv2->check_seek_stop = FALSE;
530   lv2->eos_reached = FALSE;
531   lv2->tags_pushed = FALSE;
532 
533   GST_INFO_OBJECT (base, "starting");
534 
535   return TRUE;
536 }
537 
538 static gboolean
gst_lv2_source_stop(GstBaseSrc * base)539 gst_lv2_source_stop (GstBaseSrc * base)
540 {
541   GstLV2Source *lv2 = (GstLV2Source *) base;
542 
543   GST_INFO_OBJECT (base, "stopping");
544   return gst_lv2_cleanup (&lv2->lv2, (GstObject *) lv2);
545 }
546 
547 /* GObject vmethods implementation */
548 static void
gst_lv2_source_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)549 gst_lv2_source_set_property (GObject * object, guint prop_id,
550     const GValue * value, GParamSpec * pspec)
551 {
552   GstLV2Source *self = (GstLV2Source *) object;
553 
554   switch (prop_id) {
555     case GST_LV2_SOURCE_PROP_SAMPLES_PER_BUFFER:
556       self->samples_per_buffer = g_value_get_int (value);
557       gst_base_src_set_blocksize (GST_BASE_SRC (self),
558           GST_AUDIO_INFO_BPF (&self->info) * self->samples_per_buffer);
559       break;
560     case GST_LV2_SOURCE_PROP_IS_LIVE:
561       gst_base_src_set_live (GST_BASE_SRC (self), g_value_get_boolean (value));
562       break;
563     case GST_LV2_SOURCE_PROP_TIMESTAMP_OFFSET:
564       self->timestamp_offset = g_value_get_int64 (value);
565       break;
566     case GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PUSH:
567       GST_BASE_SRC (self)->can_activate_push = g_value_get_boolean (value);
568       break;
569     case GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PULL:
570       self->can_activate_pull = g_value_get_boolean (value);
571       break;
572     default:
573       gst_lv2_object_set_property (&self->lv2, object, prop_id, value, pspec);
574       break;
575   }
576 }
577 
578 static void
gst_lv2_source_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)579 gst_lv2_source_get_property (GObject * object, guint prop_id, GValue * value,
580     GParamSpec * pspec)
581 {
582   GstLV2Source *self = (GstLV2Source *) object;
583 
584   switch (prop_id) {
585     case GST_LV2_SOURCE_PROP_SAMPLES_PER_BUFFER:
586       g_value_set_int (value, self->samples_per_buffer);
587       break;
588     case GST_LV2_SOURCE_PROP_IS_LIVE:
589       g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (self)));
590       break;
591     case GST_LV2_SOURCE_PROP_TIMESTAMP_OFFSET:
592       g_value_set_int64 (value, self->timestamp_offset);
593       break;
594     case GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PUSH:
595       g_value_set_boolean (value, GST_BASE_SRC (self)->can_activate_push);
596       break;
597     case GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PULL:
598       g_value_set_boolean (value, self->can_activate_pull);
599       break;
600     default:
601       gst_lv2_object_get_property (&self->lv2, object, prop_id, value, pspec);
602       break;
603   }
604 }
605 
606 static void
gst_lv2_source_finalize(GObject * object)607 gst_lv2_source_finalize (GObject * object)
608 {
609   GstLV2Source *self = (GstLV2Source *) object;
610 
611   gst_lv2_finalize (&self->lv2);
612 
613   G_OBJECT_CLASS (parent_class)->finalize (object);
614 }
615 
616 
617 static void
gst_lv2_source_base_init(gpointer g_class)618 gst_lv2_source_base_init (gpointer g_class)
619 {
620   GstLV2SourceClass *klass = (GstLV2SourceClass *) g_class;
621   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
622   GstPadTemplate *pad_template;
623   GstCaps *srccaps;
624 
625   gst_lv2_class_init (&klass->lv2, G_TYPE_FROM_CLASS (klass));
626 
627   gst_lv2_element_class_set_metadata (&klass->lv2, element_class,
628       "Source/Audio/LV2");
629 
630   srccaps = gst_caps_new_simple ("audio/x-raw",
631       "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
632       "channels", G_TYPE_INT, klass->lv2.out_group.ports->len,
633       "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
634       "layout", G_TYPE_STRING, "interleaved", NULL);
635 
636   pad_template =
637       gst_pad_template_new (GST_BASE_TRANSFORM_SRC_NAME, GST_PAD_SRC,
638       GST_PAD_ALWAYS, srccaps);
639   gst_element_class_add_pad_template (element_class, pad_template);
640 
641   gst_caps_unref (srccaps);
642 }
643 
644 static void
gst_lv2_source_base_finalize(GstLV2SourceClass * lv2_class)645 gst_lv2_source_base_finalize (GstLV2SourceClass * lv2_class)
646 {
647   gst_lv2_class_finalize (&lv2_class->lv2);
648 }
649 
650 static void
gst_lv2_source_class_init(GstLV2SourceClass * klass)651 gst_lv2_source_class_init (GstLV2SourceClass * klass)
652 {
653   GObjectClass *gobject_class = (GObjectClass *) klass;
654   GstBaseSrcClass *src_class = (GstBaseSrcClass *) klass;
655 
656   GST_DEBUG ("class_init %p", klass);
657 
658   gobject_class->set_property = gst_lv2_source_set_property;
659   gobject_class->get_property = gst_lv2_source_get_property;
660   gobject_class->finalize = gst_lv2_source_finalize;
661 
662   src_class->set_caps = gst_lv2_source_set_caps;
663   src_class->fixate = gst_lv2_source_fixate;
664   src_class->is_seekable = gst_lv2_source_is_seekable;
665   src_class->do_seek = gst_lv2_source_do_seek;
666   src_class->query = gst_lv2_source_query;
667   src_class->get_times = gst_lv2_source_get_times;
668   src_class->start = gst_lv2_source_start;
669   src_class->stop = gst_lv2_source_stop;
670   src_class->fill = gst_lv2_source_fill;
671 
672   g_object_class_install_property (gobject_class,
673       GST_LV2_SOURCE_PROP_SAMPLES_PER_BUFFER,
674       g_param_spec_int ("samplesperbuffer", "Samples per buffer",
675           "Number of samples in each outgoing buffer", 1, G_MAXINT, 1024,
676           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
677 
678   g_object_class_install_property (gobject_class, GST_LV2_SOURCE_PROP_IS_LIVE,
679       g_param_spec_boolean ("is-live", "Is Live",
680           "Whether to act as a live source", FALSE,
681           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
682 
683   g_object_class_install_property (gobject_class,
684       GST_LV2_SOURCE_PROP_TIMESTAMP_OFFSET,
685       g_param_spec_int64 ("timestamp-offset", "Timestamp offset",
686           "An offset added to timestamps set on buffers (in ns)", G_MININT64,
687           G_MAXINT64, G_GINT64_CONSTANT (0),
688           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
689 
690   g_object_class_install_property (gobject_class,
691       GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PUSH,
692       g_param_spec_boolean ("can-activate-push", "Can activate push",
693           "Can activate in push mode", TRUE,
694           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
695 
696   g_object_class_install_property (gobject_class,
697       GST_LV2_SOURCE_PROP_CAN_ACTIVATE_PULL,
698       g_param_spec_boolean ("can-activate-pull", "Can activate pull",
699           "Can activate in pull mode", FALSE,
700           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
701 
702   gst_lv2_class_install_properties (&klass->lv2, gobject_class,
703       GST_LV2_SOURCE_PROP_LAST);
704 }
705 
706 static void
gst_lv2_source_init(GstLV2Source * self,GstLV2SourceClass * klass)707 gst_lv2_source_init (GstLV2Source * self, GstLV2SourceClass * klass)
708 {
709   gst_lv2_init (&self->lv2, &klass->lv2);
710 
711   gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
712   gst_base_src_set_blocksize (GST_BASE_SRC (self), -1);
713 
714   self->samples_per_buffer = 1024;
715   self->generate_samples_per_buffer = self->samples_per_buffer;
716 }
717 
718 void
gst_lv2_source_register_element(GstPlugin * plugin,GstStructure * lv2_meta)719 gst_lv2_source_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
720 {
721   GTypeInfo info = {
722     sizeof (GstLV2SourceClass),
723     (GBaseInitFunc) gst_lv2_source_base_init,
724     (GBaseFinalizeFunc) gst_lv2_source_base_finalize,
725     (GClassInitFunc) gst_lv2_source_class_init,
726     NULL,
727     NULL,
728     sizeof (GstLV2Source),
729     0,
730     (GInstanceInitFunc) gst_lv2_source_init,
731   };
732   const gchar *type_name =
733       gst_structure_get_string (lv2_meta, "element-type-name");
734   GType element_type =
735       g_type_register_static (GST_TYPE_BASE_SRC, type_name, &info, 0);
736   gboolean can_do_presets;
737 
738   /* register interfaces */
739   gst_structure_get_boolean (lv2_meta, "can-do-presets", &can_do_presets);
740   if (can_do_presets) {
741     const GInterfaceInfo preset_interface_info = {
742       (GInterfaceInitFunc) gst_lv2_source_preset_interface_init,
743       NULL,
744       NULL
745     };
746 
747     g_type_add_interface_static (element_type, GST_TYPE_PRESET,
748         &preset_interface_info);
749   }
750 
751   gst_element_register (plugin, type_name, GST_RANK_NONE, element_type);
752 
753   if (!parent_class)
754     parent_class = g_type_class_ref (GST_TYPE_BASE_SRC);
755 }
756