b645e6721b2b4ffa7f3aad667aa7e45f28a5d324
[platform/upstream/gst-editing-services.git] / ges / ges-title-source.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
3  *               2010 Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
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 GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * SECTION:gestitlesource
23  * @title: GESTitleSource
24  * @short_description: render stand-alone text titles
25  *
26  * #GESTitleSource is a GESTimelineElement that implements the notion
27  * of titles in GES.
28  */
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "ges-internal.h"
34 #include "ges-track-element.h"
35 #include "ges-title-source.h"
36 #include "ges-video-test-source.h"
37
38 #define DEFAULT_TEXT ""
39 #define DEFAULT_FONT_DESC "Serif 36"
40
41 struct _GESTitleSourcePrivate
42 {
43   gchar *text;
44   gchar *font_desc;
45   GESTextHAlign halign;
46   GESTextVAlign valign;
47   guint32 color;
48   guint32 background;
49   gdouble xpos;
50   gdouble ypos;
51   GstElement *text_el;
52   GstElement *background_el;
53 };
54
55 G_DEFINE_TYPE_WITH_PRIVATE (GESTitleSource, ges_title_source,
56     GES_TYPE_VIDEO_SOURCE);
57
58 enum
59 {
60   PROP_0,
61 };
62
63 static void ges_title_source_dispose (GObject * object);
64
65 static void ges_title_source_get_property (GObject * object, guint
66     property_id, GValue * value, GParamSpec * pspec);
67
68 static void ges_title_source_set_property (GObject * object, guint
69     property_id, const GValue * value, GParamSpec * pspec);
70
71 static GstElement *ges_title_source_create_source (GESTrackElement * self);
72
73 static gboolean
74 _lookup_child (GESTimelineElement * object,
75     const gchar * prop_name, GObject ** element, GParamSpec ** pspec)
76 {
77   gboolean res;
78
79   gchar *clean_name;
80
81   if (!g_strcmp0 (prop_name, "background"))
82     clean_name = g_strdup ("foreground-color");
83   else if (!g_strcmp0 (prop_name, "GstTextOverlay:background"))
84     clean_name = g_strdup ("foreground-color");
85   else
86     clean_name = g_strdup (prop_name);
87
88   res =
89       GES_TIMELINE_ELEMENT_CLASS (ges_title_source_parent_class)->lookup_child
90       (object, clean_name, element, pspec);
91
92   g_free (clean_name);
93
94   return res;
95 }
96
97 static void
98 ges_title_source_class_init (GESTitleSourceClass * klass)
99 {
100   GObjectClass *object_class = G_OBJECT_CLASS (klass);
101   GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass);
102   GESTimelineElementClass *timeline_element_class =
103       GES_TIMELINE_ELEMENT_CLASS (klass);
104
105   object_class->get_property = ges_title_source_get_property;
106   object_class->set_property = ges_title_source_set_property;
107   object_class->dispose = ges_title_source_dispose;
108
109   timeline_element_class->lookup_child = _lookup_child;
110   source_class->ABI.abi.disable_scale_in_compositor = TRUE;
111   source_class->create_source = ges_title_source_create_source;
112
113   GES_TRACK_ELEMENT_CLASS_DEFAULT_HAS_INTERNAL_SOURCE (klass) = FALSE;
114 }
115
116 static void
117 ges_title_source_init (GESTitleSource * self)
118 {
119   self->priv = ges_title_source_get_instance_private (self);
120
121   self->priv->text = g_strdup (DEFAULT_TEXT);
122   self->priv->font_desc = g_strdup (DEFAULT_FONT_DESC);
123   self->priv->text_el = NULL;
124   self->priv->halign = DEFAULT_HALIGNMENT;
125   self->priv->valign = DEFAULT_VALIGNMENT;
126   self->priv->color = G_MAXUINT32;
127   self->priv->background = G_MAXUINT32;
128   self->priv->xpos = 0.5;
129   self->priv->ypos = 0.5;
130   self->priv->background_el = NULL;
131 }
132
133 static void
134 ges_title_source_dispose (GObject * object)
135 {
136   GESTitleSource *self = GES_TITLE_SOURCE (object);
137   if (self->priv->text) {
138     g_free (self->priv->text);
139   }
140
141   if (self->priv->font_desc) {
142     g_free (self->priv->font_desc);
143   }
144
145   if (self->priv->text_el) {
146     gst_object_unref (self->priv->text_el);
147     self->priv->text_el = NULL;
148   }
149
150   if (self->priv->background_el) {
151     gst_object_unref (self->priv->background_el);
152     self->priv->background_el = NULL;
153   }
154
155   G_OBJECT_CLASS (ges_title_source_parent_class)->dispose (object);
156 }
157
158 static void
159 ges_title_source_get_property (GObject * object,
160     guint property_id, GValue * value, GParamSpec * pspec)
161 {
162   switch (property_id) {
163     default:
164       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
165   }
166 }
167
168 static void
169 ges_title_source_set_property (GObject * object,
170     guint property_id, const GValue * value, GParamSpec * pspec)
171 {
172   switch (property_id) {
173     default:
174       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
175   }
176 }
177
178 static GstElement *
179 ges_title_source_create_source (GESTrackElement * object)
180 {
181   GstElement *topbin, *background, *text;
182   GstPad *src, *pad;
183
184   GESTitleSource *self = GES_TITLE_SOURCE (object);
185   GESTitleSourcePrivate *priv = self->priv;
186   const gchar *bg_props[] = { "pattern", "foreground-color", NULL };
187   const gchar *text_props[] = { "text", "font-desc", "valignment", "halignment",
188     "color", "xpos", "ypos", "x-absolute", "y-absolute", "outline-color",
189     "shaded-background",
190     "text-x", "text-y", "text-width", "text-height", NULL
191   };
192
193   topbin = gst_bin_new ("titlesrc-bin");
194   background = gst_element_factory_make ("videotestsrc", "titlesrc-bg");
195
196   text = gst_element_factory_make ("textoverlay", "titlsrc-text");
197   if (priv->text) {
198     g_object_set (text, "text", priv->text, NULL);
199   }
200   if (priv->font_desc) {
201     g_object_set (text, "font-desc", priv->font_desc, NULL);
202   }
203   g_object_set (text, "valignment", (gint) priv->valign, "halignment",
204       (gint) priv->halign, NULL);
205   g_object_set (text, "color", (guint) self->priv->color, NULL);
206   g_object_set (text, "xpos", (gdouble) self->priv->xpos, NULL);
207   g_object_set (text, "ypos", (gdouble) self->priv->ypos, NULL);
208
209
210   g_object_set (background, "pattern", (gint) GES_VIDEO_TEST_PATTERN_SOLID,
211       NULL);
212   g_object_set (background, "foreground-color", (guint) self->priv->background,
213       NULL);
214
215   gst_bin_add_many (GST_BIN (topbin), background, text, NULL);
216
217   gst_element_link_pads_full (background, "src", text, "video_sink",
218       GST_PAD_LINK_CHECK_NOTHING);
219
220   pad = gst_element_get_static_pad (text, "src");
221   src = gst_ghost_pad_new ("src", pad);
222   gst_object_unref (pad);
223   gst_element_add_pad (topbin, src);
224
225   gst_object_ref (text);
226   gst_object_ref (background);
227
228   priv->text_el = text;
229   priv->background_el = background;
230
231   ges_track_element_add_children_props (object, text, NULL, NULL, text_props);
232   ges_track_element_add_children_props (object, background, NULL, NULL,
233       bg_props);
234
235   return topbin;
236 }
237
238 /**
239  * ges_title_source_set_text:
240  * @self: the #GESTitleSource* to set text on
241  * @text: the text to render. an internal copy of this text will be
242  * made.
243  *
244  * Sets the text this track element will render.
245  *
246  * Deprecated: use ges_track_element_get/set_children_properties on the
247  * GESTrackElement instead
248  */
249
250 void
251 ges_title_source_set_text (GESTitleSource * self, const gchar * text)
252 {
253   if (self->priv->text)
254     g_free (self->priv->text);
255
256   GST_DEBUG ("self:%p, text:%s", self, text);
257
258   self->priv->text = g_strdup (text);
259   if (self->priv->text_el)
260     g_object_set (self->priv->text_el, "text", text, NULL);
261 }
262
263 /**
264  * ges_title_source_set_font_desc:
265  * @self: the #GESTitleSource
266  * @font_desc: the pango font description
267  *
268  * Set the pango font description this source will use to render
269  * the text.
270  */
271
272 void
273 ges_title_source_set_font_desc (GESTitleSource * self, const gchar * font_desc)
274 {
275   if (self->priv->font_desc)
276     g_free (self->priv->font_desc);
277
278   GST_DEBUG ("self:%p, font_dec:%s", self, font_desc);
279
280   self->priv->font_desc = g_strdup (font_desc);
281   if (self->priv->text_el)
282     g_object_set (self->priv->text_el, "font-desc", font_desc, NULL);
283 }
284
285 /**
286  * ges_title_source_set_valignment:
287  * @self: the #GESTitleSource* to set text on
288  * @valign: #GESTextVAlign
289  *
290  * Sets the vertical aligment of the text.
291  */
292 void
293 ges_title_source_set_valignment (GESTitleSource * self, GESTextVAlign valign)
294 {
295   GST_DEBUG ("self:%p, valign:%d", self, valign);
296
297   self->priv->valign = valign;
298   if (self->priv->text_el)
299     g_object_set (self->priv->text_el, "valignment", valign, NULL);
300 }
301
302 /**
303  * ges_title_source_set_halignment:
304  * @self: the #GESTitleSource* to set text on
305  * @halign: #GESTextHAlign
306  *
307  * Sets the vertical aligment of the text.
308  */
309 void
310 ges_title_source_set_halignment (GESTitleSource * self, GESTextHAlign halign)
311 {
312   GST_DEBUG ("self:%p, halign:%d", self, halign);
313
314   self->priv->halign = halign;
315   if (self->priv->text_el)
316     g_object_set (self->priv->text_el, "halignment", halign, NULL);
317 }
318
319 /**
320  * ges_title_source_set_text_color:
321  * @self: the #GESTitleSource* to set
322  * @color: the color @self is being set to
323  *
324  * Sets the color of the text.
325  */
326 void
327 ges_title_source_set_text_color (GESTitleSource * self, guint32 color)
328 {
329   GST_DEBUG ("self:%p, color:%d", self, color);
330
331   self->priv->color = color;
332   if (self->priv->text_el)
333     g_object_set (self->priv->text_el, "color", color, NULL);
334 }
335
336 /**
337  * ges_title_source_set_background_color:
338  * @self: the #GESTitleSource* to set
339  * @color: the color @self is being set to
340  *
341  * Sets the color of the background
342  */
343 void
344 ges_title_source_set_background_color (GESTitleSource * self, guint32 color)
345 {
346   GST_DEBUG ("self:%p, background color:%d", self, color);
347
348   self->priv->background = color;
349   if (self->priv->background_el)
350     g_object_set (self->priv->background_el, "foreground-color", color, NULL);
351 }
352
353 /**
354  * ges_title_source_set_xpos:
355  * @self: the #GESTitleSource* to set
356  * @position: the horizontal position @self is being set to
357  *
358  * Sets the horizontal position of the text.
359  */
360 void
361 ges_title_source_set_xpos (GESTitleSource * self, gdouble position)
362 {
363   GST_DEBUG ("self:%p, xpos:%f", self, position);
364
365   self->priv->xpos = position;
366   if (self->priv->text_el)
367     g_object_set (self->priv->text_el, "xpos", position, NULL);
368 }
369
370 /**
371  * ges_title_source_set_ypos:
372  * @self: the #GESTitleSource* to set
373  * @position: the color @self is being set to
374  *
375  * Sets the vertical position of the text.
376  */
377 void
378 ges_title_source_set_ypos (GESTitleSource * self, gdouble position)
379 {
380   GST_DEBUG ("self:%p, ypos:%f", self, position);
381
382   self->priv->ypos = position;
383   if (self->priv->text_el)
384     g_object_set (self->priv->text_el, "ypos", position, NULL);
385 }
386
387 /**
388  * ges_title_source_get_text:
389  * @source: a #GESTitleSource
390  *
391  * Get the text currently set on the @source.
392  *
393  * Returns: (transfer full): The text currently set on the @source.
394  *
395  * Deprecated: 1.16: Use ges_timeline_element_get_child_property instead
396  * (this actually returns a newly allocated string)
397  */
398 const gchar *
399 ges_title_source_get_text (GESTitleSource * source)
400 {
401   gchar *text;
402
403   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source), "text",
404       &text, NULL);
405
406   return text;
407 }
408
409 /**
410  * ges_title_source_get_font_desc:
411  * @source: a #GESTitleSource
412  *
413  * Get the pango font description used by @source.
414  *
415  * Returns: (transfer full): The pango font description used by this
416  * @source.
417  *
418  * Deprecated: 1.16: Use ges_timeline_element_get_child_property instead
419  * (this actually returns a newly allocated string)
420  */
421 const gchar *
422 ges_title_source_get_font_desc (GESTitleSource * source)
423 {
424   gchar *font_desc;
425
426   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source),
427       "font-desc", &font_desc, NULL);
428
429   return font_desc;
430 }
431
432 /**
433  * ges_title_source_get_halignment:
434  * @source: a #GESTitleSource
435  *
436  * Get the horizontal aligment used by @source.
437  *
438  * Returns: The horizontal aligment used by @source.
439  */
440 GESTextHAlign
441 ges_title_source_get_halignment (GESTitleSource * source)
442 {
443   GESTextHAlign halign;
444
445   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source),
446       "halignment", &halign, NULL);
447
448   return halign;
449 }
450
451 /**
452  * ges_title_source_get_valignment:
453  * @source: a #GESTitleSource
454  *
455  * Get the vertical aligment used by @source.
456  *
457  * Returns: The vertical aligment used by @source.
458  */
459 GESTextVAlign
460 ges_title_source_get_valignment (GESTitleSource * source)
461 {
462   GESTextVAlign valign;
463
464   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source),
465       "valignment", &valign, NULL);
466
467   return valign;
468 }
469
470 /**
471  * ges_title_source_get_text_color:
472  * @source: a #GESTitleSource
473  *
474  * Get the color used by @source.
475  *
476  * Returns: The color used by @source.
477  */
478 const guint32
479 ges_title_source_get_text_color (GESTitleSource * source)
480 {
481   guint32 color;
482
483   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source), "color",
484       &color, NULL);
485
486   return color;
487 }
488
489 /**
490  * ges_title_source_get_background_color:
491  * @source: a #GESTitleSource
492  *
493  * Get the background used by @source.
494  *
495  * Returns: The background used by @source.
496  */
497 const guint32
498 ges_title_source_get_background_color (GESTitleSource * source)
499 {
500   guint32 color;
501
502   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source),
503       "foreground-color", &color, NULL);
504
505   return color;
506 }
507
508 /**
509  * ges_title_source_get_xpos:
510  * @source: a #GESTitleSource
511  *
512  * Get the horizontal position used by @source.
513  *
514  * Returns: The horizontal position used by @source.
515  */
516 const gdouble
517 ges_title_source_get_xpos (GESTitleSource * source)
518 {
519   gdouble xpos;
520
521   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source), "xpos",
522       &xpos, NULL);
523
524   return xpos;
525 }
526
527 /**
528  * ges_title_source_get_ypos:
529  * @source: a #GESTitleSource
530  *
531  * Get the vertical position used by @source.
532  *
533  * Returns: The vertical position used by @source.
534  */
535 const gdouble
536 ges_title_source_get_ypos (GESTitleSource * source)
537 {
538   gdouble ypos;
539
540   ges_track_element_get_child_properties (GES_TRACK_ELEMENT (source), "ypos",
541       &ypos, NULL);
542
543   return ypos;
544 }
545
546 /* ges_title_source_new:
547  *
548  * Creates a new #GESTitleSource.
549  *
550  * Returns: (transfer floating) (nullable): The newly created #GESTitleSource,
551  * or %NULL if there was an error.
552  */
553 GESTitleSource *
554 ges_title_source_new (void)
555 {
556   GESTitleSource *res;
557   GESAsset *asset = ges_asset_request (GES_TYPE_TITLE_SOURCE, NULL, NULL);
558
559   res = GES_TITLE_SOURCE (ges_asset_extract (asset, NULL));
560   gst_object_unref (asset);
561
562   return res;
563 }