1 /* GStreamer base utils library missing plugins support
2 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * SECTION:gstpbutilsmissingplugins
22 * @title: Missing plugins
23 * @short_description: Create, recognise and parse missing-plugins messages
24 *
25 * Functions to create, recognise and parse missing-plugins messages for
26 * applications and elements.
27 *
28 * Missing-plugin messages are posted on the bus by elements like decodebin
29 * or playbin if they can't find an appropriate source element or decoder
30 * element. The application can use these messages for two things:
31 *
32 * * concise error/problem reporting to the user mentioning what exactly
33 * is missing, see gst_missing_plugin_message_get_description()
34 *
35 * * initiate installation of missing plugins, see
36 * gst_missing_plugin_message_get_installer_detail() and
37 * gst_install_plugins_async()
38 *
39 * Applications may also create missing-plugin messages themselves to install
40 * required elements that are missing, using the install mechanism mentioned
41 * above.
42 *
43 */
44
45 #ifdef HAVE_CONFIG_H
46 # include "config.h"
47 #endif
48
49 #ifdef HAVE_SYS_TYPES_H
50 # include <sys/types.h>
51 #endif
52 #ifdef HAVE_UNISTD_H
53 # include <unistd.h> /* getpid on UNIX */
54 #endif
55 #ifdef HAVE_PROCESS_H
56 # include <process.h> /* getpid on win32 */
57 #endif
58
59 #include "gst/gst-i18n-plugin.h"
60
61 #include "pbutils.h"
62 #include "pbutils-private.h"
63
64 #include <string.h>
65
66 #define GST_DETAIL_STRING_MARKER "gstreamer"
67
68 typedef enum
69 {
70 GST_MISSING_TYPE_UNKNOWN = 0,
71 GST_MISSING_TYPE_URISOURCE,
72 GST_MISSING_TYPE_URISINK,
73 GST_MISSING_TYPE_ELEMENT,
74 GST_MISSING_TYPE_DECODER,
75 GST_MISSING_TYPE_ENCODER
76 } GstMissingType;
77
78 static const struct
79 {
80 GstMissingType type;
81 const gchar type_string[12];
82 } missing_type_mapping[] = {
83 {
84 GST_MISSING_TYPE_URISOURCE, "urisource"}, {
85 GST_MISSING_TYPE_URISINK, "urisink"}, {
86 GST_MISSING_TYPE_ELEMENT, "element"}, {
87 GST_MISSING_TYPE_DECODER, "decoder"}, {
88 GST_MISSING_TYPE_ENCODER, "encoder"}
89 };
90
91 static GstMissingType
missing_structure_get_type(const GstStructure * s)92 missing_structure_get_type (const GstStructure * s)
93 {
94 const gchar *type;
95 guint i;
96
97 type = gst_structure_get_string (s, "type");
98 g_return_val_if_fail (type != NULL, GST_MISSING_TYPE_UNKNOWN);
99
100 for (i = 0; i < G_N_ELEMENTS (missing_type_mapping); ++i) {
101 if (strcmp (missing_type_mapping[i].type_string, type) == 0)
102 return missing_type_mapping[i].type;
103 }
104
105 return GST_MISSING_TYPE_UNKNOWN;
106 }
107
108 GstCaps *
copy_and_clean_caps(const GstCaps * caps)109 copy_and_clean_caps (const GstCaps * caps)
110 {
111 GstStructure *s;
112 GstCaps *ret;
113
114 ret = gst_caps_copy (caps);
115
116 /* make caps easier to interpret, remove common fields that are likely
117 * to be irrelevant for determining the right plugin (ie. mostly fields
118 * where template caps usually have the standard MIN - MAX range as value) */
119 s = gst_caps_get_structure (ret, 0);
120 gst_structure_remove_field (s, "codec_data");
121 gst_structure_remove_field (s, "streamheader");
122 gst_structure_remove_field (s, "palette_data");
123 gst_structure_remove_field (s, "pixel-aspect-ratio");
124 gst_structure_remove_field (s, "framerate");
125 gst_structure_remove_field (s, "leaf_size");
126 gst_structure_remove_field (s, "packet_size");
127 gst_structure_remove_field (s, "block_align");
128 gst_structure_remove_field (s, "metadata-interval"); /* icy caps */
129 /* decoders/encoders almost always handle the usual width/height/channel/rate
130 * range (and if we don't remove this then the app will have a much harder
131 * time blacklisting formats it has unsuccessfully tried to install before) */
132 gst_structure_remove_field (s, "width");
133 gst_structure_remove_field (s, "depth");
134 gst_structure_remove_field (s, "height");
135 gst_structure_remove_field (s, "channels");
136 gst_structure_remove_field (s, "rate");
137 /* parsed, framed, stream-format and alignment are going to be handled by
138 * parsers and not relevant for decoders/encoders usually */
139 gst_structure_remove_field (s, "parsed");
140 gst_structure_remove_field (s, "framed");
141 gst_structure_remove_field (s, "stream-format");
142 gst_structure_remove_field (s, "alignment");
143 /* rtp fields */
144 gst_structure_remove_field (s, "config");
145 gst_structure_remove_field (s, "clock-rate");
146 gst_structure_remove_field (s, "timestamp-offset");
147 gst_structure_remove_field (s, "maxps");
148 gst_structure_remove_field (s, "seqnum-offset");
149 gst_structure_remove_field (s, "npt-start");
150 gst_structure_remove_field (s, "npt-stop");
151 gst_structure_remove_field (s, "play-speed");
152 gst_structure_remove_field (s, "play-scale");
153 gst_structure_remove_field (s, "dynamic_range");
154
155 return ret;
156 }
157
158 /**
159 * gst_missing_uri_source_message_new:
160 * @element: the #GstElement posting the message
161 * @protocol: the URI protocol the missing source needs to implement,
162 * e.g. "http" or "mms"
163 *
164 * Creates a missing-plugin message for @element to notify the application
165 * that a source element for a particular URI protocol is missing. This
166 * function is mainly for use in plugins.
167 *
168 * Returns: (transfer full): a new #GstMessage, or NULL on error
169 */
170 GstMessage *
gst_missing_uri_source_message_new(GstElement * element,const gchar * protocol)171 gst_missing_uri_source_message_new (GstElement * element,
172 const gchar * protocol)
173 {
174 GstStructure *s;
175 gchar *description;
176
177 g_return_val_if_fail (element != NULL, NULL);
178 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
179 g_return_val_if_fail (protocol != NULL, NULL);
180
181 description = gst_pb_utils_get_source_description (protocol);
182
183 s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
184 "urisource", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING,
185 description, NULL);
186
187 g_free (description);
188 return gst_message_new_element (GST_OBJECT_CAST (element), s);
189 }
190
191 /**
192 * gst_missing_uri_sink_message_new:
193 * @element: the #GstElement posting the message
194 * @protocol: the URI protocol the missing sink needs to implement,
195 * e.g. "http" or "smb"
196 *
197 * Creates a missing-plugin message for @element to notify the application
198 * that a sink element for a particular URI protocol is missing. This
199 * function is mainly for use in plugins.
200 *
201 * Returns: (transfer full): a new #GstMessage, or NULL on error
202 */
203 GstMessage *
gst_missing_uri_sink_message_new(GstElement * element,const gchar * protocol)204 gst_missing_uri_sink_message_new (GstElement * element, const gchar * protocol)
205 {
206 GstStructure *s;
207 gchar *description;
208
209 g_return_val_if_fail (element != NULL, NULL);
210 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
211 g_return_val_if_fail (protocol != NULL, NULL);
212
213 description = gst_pb_utils_get_sink_description (protocol);
214
215 s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
216 "urisink", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING,
217 description, NULL);
218
219 g_free (description);
220 return gst_message_new_element (GST_OBJECT_CAST (element), s);
221 }
222
223 /**
224 * gst_missing_element_message_new:
225 * @element: the #GstElement posting the message
226 * @factory_name: the name of the missing element (element factory),
227 * e.g. "videoscale" or "cdparanoiasrc"
228 *
229 * Creates a missing-plugin message for @element to notify the application
230 * that a certain required element is missing. This function is mainly for
231 * use in plugins.
232 *
233 * Returns: (transfer full): a new #GstMessage, or NULL on error
234 */
235 GstMessage *
gst_missing_element_message_new(GstElement * element,const gchar * factory_name)236 gst_missing_element_message_new (GstElement * element,
237 const gchar * factory_name)
238 {
239 GstStructure *s;
240 gchar *description;
241
242 g_return_val_if_fail (element != NULL, NULL);
243 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
244 g_return_val_if_fail (factory_name != NULL, NULL);
245
246 description = gst_pb_utils_get_element_description (factory_name);
247
248 s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
249 "element", "detail", G_TYPE_STRING, factory_name, "name", G_TYPE_STRING,
250 description, NULL);
251
252 g_free (description);
253 return gst_message_new_element (GST_OBJECT_CAST (element), s);
254 }
255
256 /**
257 * gst_missing_decoder_message_new:
258 * @element: the #GstElement posting the message
259 * @decode_caps: the (fixed) caps for which a decoder element is needed
260 *
261 * Creates a missing-plugin message for @element to notify the application
262 * that a decoder element for a particular set of (fixed) caps is missing.
263 * This function is mainly for use in plugins.
264 *
265 * Returns: (transfer full): a new #GstMessage, or NULL on error
266 */
267 GstMessage *
gst_missing_decoder_message_new(GstElement * element,const GstCaps * decode_caps)268 gst_missing_decoder_message_new (GstElement * element,
269 const GstCaps * decode_caps)
270 {
271 GstStructure *s;
272 GstCaps *caps;
273 gchar *description;
274
275 g_return_val_if_fail (element != NULL, NULL);
276 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
277 g_return_val_if_fail (decode_caps != NULL, NULL);
278 g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
279 g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
280 g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
281 g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
282
283 description = gst_pb_utils_get_decoder_description (decode_caps);
284 caps = copy_and_clean_caps (decode_caps);
285
286 s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
287 "decoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING,
288 description, NULL);
289
290 gst_caps_unref (caps);
291 g_free (description);
292
293 return gst_message_new_element (GST_OBJECT_CAST (element), s);
294 }
295
296 /**
297 * gst_missing_encoder_message_new:
298 * @element: the #GstElement posting the message
299 * @encode_caps: the (fixed) caps for which an encoder element is needed
300 *
301 * Creates a missing-plugin message for @element to notify the application
302 * that an encoder element for a particular set of (fixed) caps is missing.
303 * This function is mainly for use in plugins.
304 *
305 * Returns: (transfer full): a new #GstMessage, or NULL on error
306 */
307 GstMessage *
gst_missing_encoder_message_new(GstElement * element,const GstCaps * encode_caps)308 gst_missing_encoder_message_new (GstElement * element,
309 const GstCaps * encode_caps)
310 {
311 GstStructure *s;
312 GstCaps *caps;
313 gchar *description;
314
315 g_return_val_if_fail (element != NULL, NULL);
316 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
317 g_return_val_if_fail (encode_caps != NULL, NULL);
318 g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
319 g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
320 g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
321 g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
322
323 description = gst_pb_utils_get_encoder_description (encode_caps);
324 caps = copy_and_clean_caps (encode_caps);
325
326 s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
327 "encoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING,
328 description, NULL);
329
330 gst_caps_unref (caps);
331 g_free (description);
332
333 return gst_message_new_element (GST_OBJECT_CAST (element), s);
334 }
335
336 static gboolean
missing_structure_get_string_detail(const GstStructure * s,gchar ** p_detail)337 missing_structure_get_string_detail (const GstStructure * s, gchar ** p_detail)
338 {
339 const gchar *detail;
340 GType detail_type;
341
342 *p_detail = NULL;
343
344 detail_type = gst_structure_get_field_type (s, "detail");
345 if (!g_type_is_a (detail_type, G_TYPE_STRING)) {
346 GST_WARNING ("expected 'detail' field to be of G_TYPE_STRING");
347 return FALSE;
348 }
349
350 detail = gst_structure_get_string (s, "detail");
351 if (detail == NULL || *detail == '\0') {
352 GST_WARNING ("empty 'detail' field");
353 return FALSE;
354 }
355 *p_detail = g_strdup (detail);
356 return TRUE;
357 }
358
359 static gboolean
missing_structure_get_caps_detail(const GstStructure * s,GstCaps ** p_caps)360 missing_structure_get_caps_detail (const GstStructure * s, GstCaps ** p_caps)
361 {
362 const GstCaps *caps;
363 const GValue *val;
364 GType detail_type;
365
366 *p_caps = NULL;
367
368 detail_type = gst_structure_get_field_type (s, "detail");
369 if (!g_type_is_a (detail_type, GST_TYPE_CAPS)) {
370 GST_WARNING ("expected 'detail' field to be of GST_TYPE_CAPS");
371 return FALSE;
372 }
373
374 val = gst_structure_get_value (s, "detail");
375 caps = gst_value_get_caps (val);
376 if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
377 GST_WARNING ("EMPTY or ANY caps not allowed");
378 return FALSE;
379 }
380
381 *p_caps = gst_caps_copy (caps);
382 return TRUE;
383 }
384
385 /**
386 * gst_missing_plugin_message_get_installer_detail:
387 * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
388 *
389 * Returns an opaque string containing all the details about the missing
390 * element to be passed to an external installer called via
391 * gst_install_plugins_async() or gst_install_plugins_sync().
392 *
393 * This function is mainly for applications that call external plugin
394 * installation mechanisms using one of the two above-mentioned functions.
395 *
396 * Returns: a newly-allocated detail string, or NULL on error. Free string
397 * with g_free() when not needed any longer.
398 */
399 gchar *
gst_missing_plugin_message_get_installer_detail(GstMessage * msg)400 gst_missing_plugin_message_get_installer_detail (GstMessage * msg)
401 {
402 GstMissingType missing_type;
403 const gchar *progname;
404 const gchar *type;
405 GString *str = NULL;
406 gchar *detail = NULL;
407 gchar *desc;
408 const GstStructure *structure;
409
410 g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);
411
412 structure = gst_message_get_structure (msg);
413 GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, structure);
414
415 missing_type = missing_structure_get_type (structure);
416 if (missing_type == GST_MISSING_TYPE_UNKNOWN) {
417 GST_WARNING ("couldn't parse 'type' field");
418 goto error;
419 }
420
421 type = gst_structure_get_string (structure, "type");
422 g_assert (type != NULL); /* validity already checked above */
423
424 /* FIXME: use gst_installer_detail_new() here too */
425 str = g_string_new (GST_DETAIL_STRING_MARKER "|");
426 g_string_append_printf (str, "%s|", GST_API_VERSION);
427
428 progname = (const gchar *) g_get_prgname ();
429 if (progname) {
430 g_string_append_printf (str, "%s|", progname);
431 } else {
432 g_string_append_printf (str, "pid/%lu|", (gulong) getpid ());
433 }
434
435 desc = gst_missing_plugin_message_get_description (msg);
436 if (desc) {
437 g_strdelimit (desc, "|", '#');
438 g_string_append_printf (str, "%s|", desc);
439 g_free (desc);
440 } else {
441 g_string_append (str, "|");
442 }
443
444 switch (missing_type) {
445 case GST_MISSING_TYPE_URISOURCE:
446 case GST_MISSING_TYPE_URISINK:
447 case GST_MISSING_TYPE_ELEMENT:
448 if (!missing_structure_get_string_detail (structure, &detail))
449 goto error;
450 break;
451 case GST_MISSING_TYPE_DECODER:
452 case GST_MISSING_TYPE_ENCODER:{
453 GstCaps *caps = NULL;
454
455 if (!missing_structure_get_caps_detail (structure, &caps))
456 goto error;
457
458 detail = gst_caps_to_string (caps);
459 gst_caps_unref (caps);
460 break;
461 }
462 default:
463 g_return_val_if_reached (NULL);
464 }
465
466 g_string_append_printf (str, "%s-%s", type, detail);
467 g_free (detail);
468
469 return g_string_free (str, FALSE);
470
471 /* ERRORS */
472 error:
473 {
474 GST_WARNING ("Failed to parse missing-plugin msg: %" GST_PTR_FORMAT, msg);
475 if (str)
476 g_string_free (str, TRUE);
477 return NULL;
478 }
479 }
480
481 /**
482 * gst_missing_plugin_message_get_description:
483 * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
484 *
485 * Returns a localised string describing the missing feature, for use in
486 * error dialogs and the like. Should never return NULL unless @msg is not
487 * a valid missing-plugin message.
488 *
489 * This function is mainly for applications that need a human-readable string
490 * describing a missing plugin, given a previously collected missing-plugin
491 * message
492 *
493 * Returns: a newly-allocated description string, or NULL on error. Free
494 * string with g_free() when not needed any longer.
495 */
496 gchar *
gst_missing_plugin_message_get_description(GstMessage * msg)497 gst_missing_plugin_message_get_description (GstMessage * msg)
498 {
499 GstMissingType missing_type;
500 const gchar *desc;
501 gchar *ret = NULL;
502 const GstStructure *structure;
503
504 g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);
505
506 structure = gst_message_get_structure (msg);
507 GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, structure);
508
509 desc = gst_structure_get_string (structure, "name");
510 if (desc != NULL && *desc != '\0') {
511 ret = g_strdup (desc);
512 goto done;
513 }
514
515 /* fallback #1 */
516 missing_type = missing_structure_get_type (structure);
517
518 switch (missing_type) {
519 case GST_MISSING_TYPE_URISOURCE:
520 case GST_MISSING_TYPE_URISINK:
521 case GST_MISSING_TYPE_ELEMENT:{
522 gchar *detail = NULL;
523
524 if (missing_structure_get_string_detail (structure, &detail)) {
525 if (missing_type == GST_MISSING_TYPE_URISOURCE)
526 ret = gst_pb_utils_get_source_description (detail);
527 else if (missing_type == GST_MISSING_TYPE_URISINK)
528 ret = gst_pb_utils_get_sink_description (detail);
529 else
530 ret = gst_pb_utils_get_element_description (detail);
531 g_free (detail);
532 }
533 break;
534 }
535 case GST_MISSING_TYPE_DECODER:
536 case GST_MISSING_TYPE_ENCODER:{
537 GstCaps *caps = NULL;
538
539 if (missing_structure_get_caps_detail (structure, &caps)) {
540 if (missing_type == GST_MISSING_TYPE_DECODER)
541 ret = gst_pb_utils_get_decoder_description (caps);
542 else
543 ret = gst_pb_utils_get_encoder_description (caps);
544 gst_caps_unref (caps);
545 }
546 break;
547 }
548 default:
549 break;
550 }
551
552 if (ret)
553 goto done;
554
555 /* fallback #2 */
556 switch (missing_type) {
557 case GST_MISSING_TYPE_URISOURCE:
558 desc = _("Unknown source element");
559 break;
560 case GST_MISSING_TYPE_URISINK:
561 desc = _("Unknown sink element");
562 break;
563 case GST_MISSING_TYPE_ELEMENT:
564 desc = _("Unknown element");
565 break;
566 case GST_MISSING_TYPE_DECODER:
567 desc = _("Unknown decoder element");
568 break;
569 case GST_MISSING_TYPE_ENCODER:
570 desc = _("Unknown encoder element");
571 break;
572 default:
573 /* we should really never get here, but we better still return
574 * something if we do */
575 desc = _("Plugin or element of unknown type");
576 break;
577 }
578 ret = g_strdup (desc);
579
580 done:
581
582 GST_LOG ("returning '%s'", ret);
583 return ret;
584 }
585
586 /**
587 * gst_is_missing_plugin_message:
588 * @msg: a #GstMessage
589 *
590 * Checks whether @msg is a missing plugins message.
591 *
592 * Returns: %TRUE if @msg is a missing-plugins message, otherwise %FALSE.
593 */
594 gboolean
gst_is_missing_plugin_message(GstMessage * msg)595 gst_is_missing_plugin_message (GstMessage * msg)
596 {
597 const GstStructure *structure;
598
599 g_return_val_if_fail (msg != NULL, FALSE);
600 g_return_val_if_fail (GST_IS_MESSAGE (msg), FALSE);
601
602 structure = gst_message_get_structure (msg);
603 if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || structure == NULL)
604 return FALSE;
605
606 return gst_structure_has_name (structure, "missing-plugin");
607 }
608
609 /* takes ownership of the description */
610 static gchar *
gst_installer_detail_new(gchar * description,const gchar * type,const gchar * detail)611 gst_installer_detail_new (gchar * description, const gchar * type,
612 const gchar * detail)
613 {
614 const gchar *progname;
615 GString *s;
616
617 s = g_string_new (GST_DETAIL_STRING_MARKER "|");
618 g_string_append_printf (s, "%s|", GST_API_VERSION);
619
620 progname = (const gchar *) g_get_prgname ();
621 if (progname) {
622 g_string_append_printf (s, "%s|", progname);
623 } else {
624 g_string_append_printf (s, "pid/%lu|", (gulong) getpid ());
625 }
626
627 if (description) {
628 g_strdelimit (description, "|", '#');
629 g_string_append_printf (s, "%s|", description);
630 g_free (description);
631 } else {
632 g_string_append (s, "|");
633 }
634
635 g_string_append_printf (s, "%s-%s", type, detail);
636
637 return g_string_free (s, FALSE);
638 }
639
640 /**
641 * gst_missing_uri_source_installer_detail_new:
642 * @protocol: the URI protocol the missing source needs to implement,
643 * e.g. "http" or "mms"
644 *
645 * Returns an opaque string containing all the details about the missing
646 * element to be passed to an external installer called via
647 * gst_install_plugins_async() or gst_install_plugins_sync().
648 *
649 * This function is mainly for applications that call external plugin
650 * installation mechanisms using one of the two above-mentioned functions in
651 * the case where the application knows exactly what kind of plugin it is
652 * missing.
653 *
654 * Returns: a newly-allocated detail string, or NULL on error. Free string
655 * with g_free() when not needed any longer.
656 */
657 gchar *
gst_missing_uri_source_installer_detail_new(const gchar * protocol)658 gst_missing_uri_source_installer_detail_new (const gchar * protocol)
659 {
660 gchar *desc;
661
662 g_return_val_if_fail (protocol != NULL, NULL);
663
664 desc = gst_pb_utils_get_source_description (protocol);
665 return gst_installer_detail_new (desc, "urisource", protocol);
666 }
667
668 /**
669 * gst_missing_uri_sink_installer_detail_new:
670 * @protocol: the URI protocol the missing source needs to implement,
671 * e.g. "http" or "mms"
672 *
673 * Returns an opaque string containing all the details about the missing
674 * element to be passed to an external installer called via
675 * gst_install_plugins_async() or gst_install_plugins_sync().
676 *
677 * This function is mainly for applications that call external plugin
678 * installation mechanisms using one of the two above-mentioned functions in
679 * the case where the application knows exactly what kind of plugin it is
680 * missing.
681 *
682 * Returns: a newly-allocated detail string, or NULL on error. Free string
683 * with g_free() when not needed any longer.
684 */
685 gchar *
gst_missing_uri_sink_installer_detail_new(const gchar * protocol)686 gst_missing_uri_sink_installer_detail_new (const gchar * protocol)
687 {
688 gchar *desc;
689
690 g_return_val_if_fail (protocol != NULL, NULL);
691
692 desc = gst_pb_utils_get_sink_description (protocol);
693 return gst_installer_detail_new (desc, "urisink", protocol);
694 }
695
696 /**
697 * gst_missing_element_installer_detail_new:
698 * @factory_name: the name of the missing element (element factory),
699 * e.g. "videoscale" or "cdparanoiasrc"
700 *
701 * Returns an opaque string containing all the details about the missing
702 * element to be passed to an external installer called via
703 * gst_install_plugins_async() or gst_install_plugins_sync().
704 *
705 * This function is mainly for applications that call external plugin
706 * installation mechanisms using one of the two above-mentioned functions in
707 * the case where the application knows exactly what kind of plugin it is
708 * missing.
709 *
710 * Returns: a newly-allocated detail string, or NULL on error. Free string
711 * with g_free() when not needed any longer.
712 */
713 gchar *
gst_missing_element_installer_detail_new(const gchar * factory_name)714 gst_missing_element_installer_detail_new (const gchar * factory_name)
715 {
716 gchar *desc;
717
718 g_return_val_if_fail (factory_name != NULL, NULL);
719
720 desc = gst_pb_utils_get_element_description (factory_name);
721 return gst_installer_detail_new (desc, "element", factory_name);
722 }
723
724 /**
725 * gst_missing_decoder_installer_detail_new:
726 * @decode_caps: the (fixed) caps for which a decoder element is needed
727 *
728 * Returns an opaque string containing all the details about the missing
729 * element to be passed to an external installer called via
730 * gst_install_plugins_async() or gst_install_plugins_sync().
731 *
732 * This function is mainly for applications that call external plugin
733 * installation mechanisms using one of the two above-mentioned functions in
734 * the case where the application knows exactly what kind of plugin it is
735 * missing.
736 *
737 * Returns: a newly-allocated detail string, or NULL on error. Free string
738 * with g_free() when not needed any longer.
739 */
740 gchar *
gst_missing_decoder_installer_detail_new(const GstCaps * decode_caps)741 gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps)
742 {
743 GstCaps *caps;
744 gchar *detail_str, *caps_str, *desc;
745
746 g_return_val_if_fail (decode_caps != NULL, NULL);
747 g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
748 g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
749 g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
750 g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
751
752 desc = gst_pb_utils_get_decoder_description (decode_caps);
753 caps = copy_and_clean_caps (decode_caps);
754 caps_str = gst_caps_to_string (caps);
755 detail_str = gst_installer_detail_new (desc, "decoder", caps_str);
756 g_free (caps_str);
757 gst_caps_unref (caps);
758
759 return detail_str;
760 }
761
762 /**
763 * gst_missing_encoder_installer_detail_new:
764 * @encode_caps: the (fixed) caps for which an encoder element is needed
765 *
766 * Returns an opaque string containing all the details about the missing
767 * element to be passed to an external installer called via
768 * gst_install_plugins_async() or gst_install_plugins_sync().
769 *
770 * This function is mainly for applications that call external plugin
771 * installation mechanisms using one of the two above-mentioned functions in
772 * the case where the application knows exactly what kind of plugin it is
773 * missing.
774 *
775 * Returns: a newly-allocated detail string, or NULL on error. Free string
776 * with g_free() when not needed any longer.
777 */
778 gchar *
gst_missing_encoder_installer_detail_new(const GstCaps * encode_caps)779 gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps)
780 {
781 GstCaps *caps;
782 gchar *detail_str, *caps_str, *desc;
783
784 g_return_val_if_fail (encode_caps != NULL, NULL);
785 g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
786 g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
787 g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
788 g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
789
790 desc = gst_pb_utils_get_encoder_description (encode_caps);
791 caps = copy_and_clean_caps (encode_caps);
792 caps_str = gst_caps_to_string (caps);
793 detail_str = gst_installer_detail_new (desc, "encoder", caps_str);
794 g_free (caps_str);
795 gst_caps_unref (caps);
796
797 return detail_str;
798 }
799