277 /* make sure gst_init() has been called */ |
272 /* make sure gst_init() has been called */ |
278 g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE); |
273 g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE); |
279 |
274 |
280 GST_LOG ("attempting to load static plugin \"%s\" now...", name); |
275 GST_LOG ("attempting to load static plugin \"%s\" now...", name); |
281 plugin = g_object_new (GST_TYPE_PLUGIN, NULL); |
276 plugin = g_object_new (GST_TYPE_PLUGIN, NULL); |
282 if (gst_plugin_register_func (plugin, &desc, NULL) != NULL) { |
277 if (gst_plugin_register_func (plugin, &desc) != NULL) { |
283 GST_INFO ("registered static plugin \"%s\"", name); |
|
284 res = gst_default_registry_add_plugin (plugin); |
|
285 GST_INFO ("added static plugin \"%s\", result: %d", name, res); |
|
286 } |
|
287 return res; |
|
288 } |
|
289 |
|
290 /** |
|
291 * gst_plugin_register_static_full: |
|
292 * @major_version: the major version number of the GStreamer core that the |
|
293 * plugin was compiled for, you can just use GST_VERSION_MAJOR here |
|
294 * @minor_version: the minor version number of the GStreamer core that the |
|
295 * plugin was compiled for, you can just use GST_VERSION_MINOR here |
|
296 * @name: a unique name of the plugin (ideally prefixed with an application- or |
|
297 * library-specific namespace prefix in order to avoid name conflicts in |
|
298 * case a similar plugin with the same name ever gets added to GStreamer) |
|
299 * @description: description of the plugin |
|
300 * @init_full_func: pointer to the init function with user data of this plugin. |
|
301 * @version: version string of the plugin |
|
302 * @license: effective license of plugin. Must be one of the approved licenses |
|
303 * (see #GstPluginDesc above) or the plugin will not be registered. |
|
304 * @source: source module plugin belongs to |
|
305 * @package: shipped package plugin belongs to |
|
306 * @origin: URL to provider of plugin |
|
307 * @user_data: gpointer to user data |
|
308 * |
|
309 * Registers a static plugin, ie. a plugin which is private to an application |
|
310 * or library and contained within the application or library (as opposed to |
|
311 * being shipped as a separate module file) with a #GstPluginInitFullFunc |
|
312 * which allows user data to be passed to the callback function (useful |
|
313 * for bindings). |
|
314 * |
|
315 * You must make sure that GStreamer has been initialised (with gst_init() or |
|
316 * via gst_init_get_option_group()) before calling this function. |
|
317 * |
|
318 * Returns: TRUE if the plugin was registered correctly, otherwise FALSE. |
|
319 * |
|
320 * Since: 0.10.24 |
|
321 * |
|
322 */ |
|
323 #ifdef __SYMBIAN32__ |
|
324 EXPORT_C |
|
325 #endif |
|
326 |
|
327 gboolean |
|
328 gst_plugin_register_static_full (gint major_version, gint minor_version, |
|
329 const gchar * name, gchar * description, |
|
330 GstPluginInitFullFunc init_full_func, const gchar * version, |
|
331 const gchar * license, const gchar * source, const gchar * package, |
|
332 const gchar * origin, gpointer user_data) |
|
333 { |
|
334 #ifdef __SYMBIAN32__ |
|
335 GstPluginDesc desc; |
|
336 GstPlugin *plugin; |
|
337 gboolean res = FALSE; |
|
338 |
|
339 desc.major_version = major_version; |
|
340 desc.minor_version = minor_version; |
|
341 desc.name = name; |
|
342 desc.description = description; |
|
343 desc.plugin_init = (GstPluginInitFunc)init_full_func; |
|
344 desc.version = version; |
|
345 desc.license = license; |
|
346 desc.source = source; |
|
347 desc.package = package; |
|
348 desc.origin = origin; |
|
349 #else |
|
350 GstPluginDesc desc = { major_version, minor_version, name, description, |
|
351 (GstPluginInitFunc) init_full_func, version, license, source, package, |
|
352 origin, |
|
353 }; |
|
354 GstPlugin *plugin; |
|
355 gboolean res = FALSE; |
|
356 #endif |
|
357 g_return_val_if_fail (name != NULL, FALSE); |
|
358 g_return_val_if_fail (description != NULL, FALSE); |
|
359 g_return_val_if_fail (init_full_func != NULL, FALSE); |
|
360 g_return_val_if_fail (version != NULL, FALSE); |
|
361 g_return_val_if_fail (license != NULL, FALSE); |
|
362 g_return_val_if_fail (source != NULL, FALSE); |
|
363 g_return_val_if_fail (package != NULL, FALSE); |
|
364 g_return_val_if_fail (origin != NULL, FALSE); |
|
365 |
|
366 /* make sure gst_init() has been called */ |
|
367 g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE); |
|
368 |
|
369 GST_LOG ("attempting to load static plugin \"%s\" now...", name); |
|
370 plugin = g_object_new (GST_TYPE_PLUGIN, NULL); |
|
371 if (gst_plugin_register_func (plugin, &desc, user_data) != NULL) { |
|
372 GST_INFO ("registered static plugin \"%s\"", name); |
278 GST_INFO ("registered static plugin \"%s\"", name); |
373 res = gst_default_registry_add_plugin (plugin); |
279 res = gst_default_registry_add_plugin (plugin); |
374 GST_INFO ("added static plugin \"%s\", result: %d", name, res); |
280 GST_INFO ("added static plugin \"%s\", result: %d", name, res); |
375 } |
281 } |
376 return res; |
282 return res; |
1310 for (g = list; g; g = g->next) { |
1130 for (g = list; g; g = g->next) { |
1311 gst_object_unref (GST_PLUGIN_CAST (g->data)); |
1131 gst_object_unref (GST_PLUGIN_CAST (g->data)); |
1312 } |
1132 } |
1313 g_list_free (list); |
1133 g_list_free (list); |
1314 } |
1134 } |
1315 |
|
1316 /* ===== plugin dependencies ===== */ |
|
1317 |
|
1318 /* Scenarios: |
|
1319 * ENV + xyz where ENV can contain multiple values separated by SEPARATOR |
|
1320 * xyz may be "" (if ENV contains path to file rather than dir) |
|
1321 * ENV + *xyz same as above, but xyz acts as suffix filter |
|
1322 * ENV + xyz* same as above, but xyz acts as prefix filter (is this needed?) |
|
1323 * ENV + *xyz* same as above, but xyz acts as strstr filter (is this needed?) |
|
1324 * |
|
1325 * same as above, with additional paths hard-coded at compile-time: |
|
1326 * - only check paths + ... if ENV is not set or yields not paths |
|
1327 * - always check paths + ... in addition to ENV |
|
1328 * |
|
1329 * When user specifies set of environment variables, he/she may also use e.g. |
|
1330 * "HOME/.mystuff/plugins", and we'll expand the content of $HOME with the |
|
1331 * remainder |
|
1332 */ |
|
1333 |
|
1334 /* we store in registry: |
|
1335 * sets of: |
|
1336 * { |
|
1337 * - environment variables (array of strings) |
|
1338 * - last hash of env variable contents (uint) (so we can avoid doing stats |
|
1339 * if one of the env vars has changed; premature optimisation galore) |
|
1340 * - hard-coded paths (array of strings) |
|
1341 * - xyz filename/suffix/prefix strings (array of strings) |
|
1342 * - flags (int) |
|
1343 * - last hash of file/dir stats (int) |
|
1344 * } |
|
1345 * (= struct GstPluginDep) |
|
1346 */ |
|
1347 |
|
1348 static guint |
|
1349 gst_plugin_ext_dep_get_env_vars_hash (GstPlugin * plugin, GstPluginDep * dep) |
|
1350 { |
|
1351 gchar **e; |
|
1352 guint hash; |
|
1353 |
|
1354 /* there's no deeper logic to what we do here; all we want to know (when |
|
1355 * checking if the plugin needs to be rescanned) is whether the content of |
|
1356 * one of the environment variables in the list is different from when it |
|
1357 * was last scanned */ |
|
1358 hash = 0; |
|
1359 for (e = dep->env_vars; e != NULL && *e != NULL; ++e) { |
|
1360 const gchar *val; |
|
1361 gchar env_var[256]; |
|
1362 |
|
1363 /* order matters: "val",NULL needs to yield a different hash than |
|
1364 * NULL,"val", so do a shift here whether the var is set or not */ |
|
1365 hash = hash << 5; |
|
1366 |
|
1367 /* want environment variable at beginning of string */ |
|
1368 if (!g_ascii_isalnum (**e)) { |
|
1369 GST_WARNING_OBJECT (plugin, "string prefix is not a valid environment " |
|
1370 "variable string: %s", *e); |
|
1371 continue; |
|
1372 } |
|
1373 |
|
1374 /* user is allowed to specify e.g. "HOME/.pitivi/plugins" */ |
|
1375 g_strlcpy (env_var, *e, sizeof (env_var)); |
|
1376 g_strdelimit (env_var, "/\\", '\0'); |
|
1377 |
|
1378 if ((val = g_getenv (env_var))) |
|
1379 hash += g_str_hash (val); |
|
1380 } |
|
1381 |
|
1382 return hash; |
|
1383 } |
|
1384 #ifdef __SYMBIAN32__ |
|
1385 EXPORT_C |
|
1386 #endif |
|
1387 |
|
1388 |
|
1389 gboolean |
|
1390 _priv_plugin_deps_env_vars_changed (GstPlugin * plugin) |
|
1391 { |
|
1392 GList *l; |
|
1393 |
|
1394 for (l = plugin->priv->deps; l != NULL; l = l->next) { |
|
1395 GstPluginDep *dep = l->data; |
|
1396 |
|
1397 if (dep->env_hash != gst_plugin_ext_dep_get_env_vars_hash (plugin, dep)) |
|
1398 return TRUE; |
|
1399 } |
|
1400 |
|
1401 return FALSE; |
|
1402 } |
|
1403 |
|
1404 static GList * |
|
1405 gst_plugin_ext_dep_extract_env_vars_paths (GstPlugin * plugin, |
|
1406 GstPluginDep * dep) |
|
1407 { |
|
1408 gchar **evars; |
|
1409 GList *paths = NULL; |
|
1410 |
|
1411 for (evars = dep->env_vars; evars != NULL && *evars != NULL; ++evars) { |
|
1412 const gchar *e; |
|
1413 gchar **components; |
|
1414 |
|
1415 /* want environment variable at beginning of string */ |
|
1416 if (!g_ascii_isalnum (**evars)) { |
|
1417 GST_WARNING_OBJECT (plugin, "string prefix is not a valid environment " |
|
1418 "variable string: %s", *evars); |
|
1419 continue; |
|
1420 } |
|
1421 |
|
1422 /* user is allowed to specify e.g. "HOME/.pitivi/plugins", which we want to |
|
1423 * split into the env_var name component and the path component */ |
|
1424 components = g_strsplit_set (*evars, "/\\", 2); |
|
1425 g_assert (components != NULL); |
|
1426 |
|
1427 e = g_getenv (components[0]); |
|
1428 GST_LOG_OBJECT (plugin, "expanding %s = '%s' (path suffix: %s)", |
|
1429 components[0], GST_STR_NULL (e), GST_STR_NULL (components[1])); |
|
1430 |
|
1431 if (components[1] != NULL) { |
|
1432 g_strdelimit (components[1], "/\\", G_DIR_SEPARATOR); |
|
1433 } |
|
1434 |
|
1435 if (e != NULL && *e != '\0') { |
|
1436 gchar **arr; |
|
1437 guint i; |
|
1438 |
|
1439 arr = g_strsplit (e, G_SEARCHPATH_SEPARATOR_S, -1); |
|
1440 |
|
1441 for (i = 0; arr != NULL && arr[i] != NULL; ++i) { |
|
1442 gchar *full_path; |
|
1443 |
|
1444 if (!g_path_is_absolute (arr[i])) { |
|
1445 GST_INFO_OBJECT (plugin, "ignoring environment variable content '%s'" |
|
1446 ": either not an absolute path or not a path at all", arr[i]); |
|
1447 continue; |
|
1448 } |
|
1449 |
|
1450 if (components[1] != NULL) { |
|
1451 full_path = g_build_filename (arr[i], components[1], NULL); |
|
1452 } else { |
|
1453 full_path = g_strdup (arr[i]); |
|
1454 } |
|
1455 |
|
1456 if (!g_list_find_custom (paths, full_path, (GCompareFunc) strcmp)) { |
|
1457 GST_LOG_OBJECT (plugin, "path: '%s'", full_path); |
|
1458 paths = g_list_prepend (paths, full_path); |
|
1459 full_path = NULL; |
|
1460 } else { |
|
1461 GST_LOG_OBJECT (plugin, "path: '%s' (duplicate,ignoring)", full_path); |
|
1462 g_free (full_path); |
|
1463 } |
|
1464 } |
|
1465 |
|
1466 g_strfreev (arr); |
|
1467 } |
|
1468 |
|
1469 g_strfreev (components); |
|
1470 } |
|
1471 |
|
1472 GST_LOG_OBJECT (plugin, "Extracted %d paths from environment", |
|
1473 g_list_length (paths)); |
|
1474 |
|
1475 return paths; |
|
1476 } |
|
1477 |
|
1478 static guint |
|
1479 gst_plugin_ext_dep_get_hash_from_stat_entry (struct stat *s) |
|
1480 { |
|
1481 if (!(s->st_mode & (S_IFDIR | S_IFREG))) |
|
1482 return (guint) - 1; |
|
1483 |
|
1484 /* completely random formula */ |
|
1485 return ((s->st_size << 3) + (s->st_mtime << 5)) ^ s->st_ctime; |
|
1486 } |
|
1487 |
|
1488 static gboolean |
|
1489 gst_plugin_ext_dep_direntry_matches (GstPlugin * plugin, const gchar * entry, |
|
1490 const gchar ** filenames, GstPluginDependencyFlags flags) |
|
1491 { |
|
1492 /* no filenames specified, match all entries for now (could probably |
|
1493 * optimise by just taking the dir stat hash or so) */ |
|
1494 if (filenames == NULL || *filenames == NULL || **filenames == '\0') |
|
1495 return TRUE; |
|
1496 |
|
1497 while (*filenames != NULL) { |
|
1498 /* suffix match? */ |
|
1499 if (((flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX)) && |
|
1500 g_str_has_suffix (entry, *filenames)) { |
|
1501 return TRUE; |
|
1502 /* else it's an exact match that's needed */ |
|
1503 } else if (strcmp (entry, *filenames) == 0) { |
|
1504 return TRUE; |
|
1505 } |
|
1506 GST_LOG ("%s does not match %s, flags=0x%04x", entry, *filenames, flags); |
|
1507 ++filenames; |
|
1508 } |
|
1509 return FALSE; |
|
1510 } |
|
1511 |
|
1512 static guint |
|
1513 gst_plugin_ext_dep_scan_dir_and_match_names (GstPlugin * plugin, |
|
1514 const gchar * path, const gchar ** filenames, |
|
1515 GstPluginDependencyFlags flags, int depth) |
|
1516 { |
|
1517 const gchar *entry; |
|
1518 gboolean recurse_dirs; |
|
1519 GError *err = NULL; |
|
1520 GDir *dir; |
|
1521 guint hash = 0; |
|
1522 |
|
1523 recurse_dirs = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); |
|
1524 |
|
1525 dir = g_dir_open (path, 0, &err); |
|
1526 if (dir == NULL) { |
|
1527 GST_DEBUG_OBJECT (plugin, "g_dir_open(%s) failed: %s", path, err->message); |
|
1528 g_error_free (err); |
|
1529 return (guint) - 1; |
|
1530 } |
|
1531 |
|
1532 /* FIXME: we're assuming here that we always get the directory entries in |
|
1533 * the same order, and not in a random order */ |
|
1534 while ((entry = g_dir_read_name (dir))) { |
|
1535 gboolean have_match; |
|
1536 struct stat s; |
|
1537 gchar *full_path; |
|
1538 guint fhash; |
|
1539 |
|
1540 have_match = |
|
1541 gst_plugin_ext_dep_direntry_matches (plugin, entry, filenames, flags); |
|
1542 |
|
1543 /* avoid the stat if possible */ |
|
1544 if (!have_match && !recurse_dirs) |
|
1545 continue; |
|
1546 |
|
1547 full_path = g_build_filename (path, entry, NULL); |
|
1548 if (g_stat (full_path, &s) < 0) { |
|
1549 fhash = (guint) - 1; |
|
1550 GST_LOG_OBJECT (plugin, "stat: %s (error: %s)", full_path, |
|
1551 g_strerror (errno)); |
|
1552 } else if (have_match) { |
|
1553 fhash = gst_plugin_ext_dep_get_hash_from_stat_entry (&s); |
|
1554 GST_LOG_OBJECT (plugin, "stat: %s (result: %u)", full_path, fhash); |
|
1555 } else if ((s.st_mode & (S_IFDIR))) { |
|
1556 fhash = gst_plugin_ext_dep_scan_dir_and_match_names (plugin, full_path, |
|
1557 filenames, flags, depth + 1); |
|
1558 } else { |
|
1559 /* it's not a name match, we want to recurse, but it's not a directory */ |
|
1560 g_free (full_path); |
|
1561 continue; |
|
1562 } |
|
1563 |
|
1564 hash = (hash + fhash) << 1; |
|
1565 g_free (full_path); |
|
1566 } |
|
1567 |
|
1568 g_dir_close (dir); |
|
1569 return hash; |
|
1570 } |
|
1571 |
|
1572 static guint |
|
1573 gst_plugin_ext_dep_scan_path_with_filenames (GstPlugin * plugin, |
|
1574 const gchar * path, const gchar ** filenames, |
|
1575 GstPluginDependencyFlags flags) |
|
1576 { |
|
1577 const gchar *empty_filenames[] = { "", NULL }; |
|
1578 gboolean recurse_into_dirs, partial_names; |
|
1579 guint i, hash = 0; |
|
1580 |
|
1581 /* to avoid special-casing below (FIXME?) */ |
|
1582 if (filenames == NULL || *filenames == NULL) |
|
1583 filenames = empty_filenames; |
|
1584 |
|
1585 recurse_into_dirs = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_RECURSE); |
|
1586 partial_names = !!(flags & GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX); |
|
1587 |
|
1588 /* if we can construct the exact paths to check with the data we have, just |
|
1589 * stat them one by one; this is more efficient than opening the directory |
|
1590 * and going through each entry to see if it matches one of our filenames. */ |
|
1591 if (!recurse_into_dirs && !partial_names) { |
|
1592 for (i = 0; filenames[i] != NULL; ++i) { |
|
1593 struct stat s; |
|
1594 gchar *full_path; |
|
1595 guint fhash; |
|
1596 |
|
1597 full_path = g_build_filename (path, filenames[i], NULL); |
|
1598 if (g_stat (full_path, &s) < 0) { |
|
1599 fhash = (guint) - 1; |
|
1600 GST_LOG_OBJECT (plugin, "stat: %s (error: %s)", full_path, |
|
1601 g_strerror (errno)); |
|
1602 } else { |
|
1603 fhash = gst_plugin_ext_dep_get_hash_from_stat_entry (&s); |
|
1604 GST_LOG_OBJECT (plugin, "stat: %s (result: %08x)", full_path, fhash); |
|
1605 } |
|
1606 hash = (hash + fhash) << 1; |
|
1607 g_free (full_path); |
|
1608 } |
|
1609 } else { |
|
1610 hash = gst_plugin_ext_dep_scan_dir_and_match_names (plugin, path, |
|
1611 filenames, flags, 0); |
|
1612 } |
|
1613 |
|
1614 return hash; |
|
1615 } |
|
1616 |
|
1617 static guint |
|
1618 gst_plugin_ext_dep_get_stat_hash (GstPlugin * plugin, GstPluginDep * dep) |
|
1619 { |
|
1620 gboolean paths_are_default_only; |
|
1621 GList *scan_paths; |
|
1622 guint scan_hash = 0; |
|
1623 |
|
1624 GST_LOG_OBJECT (plugin, "start"); |
|
1625 |
|
1626 paths_are_default_only = |
|
1627 dep->flags & GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY; |
|
1628 |
|
1629 scan_paths = gst_plugin_ext_dep_extract_env_vars_paths (plugin, dep); |
|
1630 |
|
1631 if (scan_paths == NULL || !paths_are_default_only) { |
|
1632 gchar **paths; |
|
1633 |
|
1634 for (paths = dep->paths; paths != NULL && *paths != NULL; ++paths) { |
|
1635 const gchar *path = *paths; |
|
1636 |
|
1637 if (!g_list_find_custom (scan_paths, path, (GCompareFunc) strcmp)) { |
|
1638 GST_LOG_OBJECT (plugin, "path: '%s'", path); |
|
1639 scan_paths = g_list_prepend (scan_paths, g_strdup (path)); |
|
1640 } else { |
|
1641 GST_LOG_OBJECT (plugin, "path: '%s' (duplicate, ignoring)", path); |
|
1642 } |
|
1643 } |
|
1644 } |
|
1645 |
|
1646 /* not that the order really matters, but it makes debugging easier */ |
|
1647 scan_paths = g_list_reverse (scan_paths); |
|
1648 |
|
1649 while (scan_paths != NULL) { |
|
1650 const gchar *path = scan_paths->data; |
|
1651 |
|
1652 scan_hash += gst_plugin_ext_dep_scan_path_with_filenames (plugin, path, |
|
1653 (const gchar **) dep->names, dep->flags); |
|
1654 scan_hash = scan_hash << 1; |
|
1655 |
|
1656 g_free (scan_paths->data); |
|
1657 scan_paths = g_list_delete_link (scan_paths, scan_paths); |
|
1658 } |
|
1659 |
|
1660 GST_LOG_OBJECT (plugin, "done, scan_hash: %08x", scan_hash); |
|
1661 return scan_hash; |
|
1662 } |
|
1663 #ifdef __SYMBIAN32__ |
|
1664 EXPORT_C |
|
1665 #endif |
|
1666 |
|
1667 |
|
1668 gboolean |
|
1669 _priv_plugin_deps_files_changed (GstPlugin * plugin) |
|
1670 { |
|
1671 GList *l; |
|
1672 |
|
1673 for (l = plugin->priv->deps; l != NULL; l = l->next) { |
|
1674 GstPluginDep *dep = l->data; |
|
1675 |
|
1676 if (dep->stat_hash != gst_plugin_ext_dep_get_stat_hash (plugin, dep)) |
|
1677 return TRUE; |
|
1678 } |
|
1679 |
|
1680 return FALSE; |
|
1681 } |
|
1682 |
|
1683 static void |
|
1684 gst_plugin_ext_dep_free (GstPluginDep * dep) |
|
1685 { |
|
1686 g_strfreev (dep->env_vars); |
|
1687 g_strfreev (dep->paths); |
|
1688 g_strfreev (dep->names); |
|
1689 g_free (dep); |
|
1690 } |
|
1691 |
|
1692 static gboolean |
|
1693 gst_plugin_ext_dep_strv_equal (gchar ** arr1, gchar ** arr2) |
|
1694 { |
|
1695 if (arr1 == arr2) |
|
1696 return TRUE; |
|
1697 if (arr1 == NULL || arr2 == NULL) |
|
1698 return FALSE; |
|
1699 for (; *arr1 != NULL && *arr2 != NULL; ++arr1, ++arr2) { |
|
1700 if (strcmp (*arr1, *arr2) != 0) |
|
1701 return FALSE; |
|
1702 } |
|
1703 return (*arr1 == *arr2); |
|
1704 } |
|
1705 |
|
1706 static gboolean |
|
1707 gst_plugin_ext_dep_equals (GstPluginDep * dep, const gchar ** env_vars, |
|
1708 const gchar ** paths, const gchar ** names, GstPluginDependencyFlags flags) |
|
1709 { |
|
1710 if (dep->flags != flags) |
|
1711 return FALSE; |
|
1712 |
|
1713 return gst_plugin_ext_dep_strv_equal (dep->env_vars, (gchar **) env_vars) && |
|
1714 gst_plugin_ext_dep_strv_equal (dep->paths, (gchar **) paths) && |
|
1715 gst_plugin_ext_dep_strv_equal (dep->names, (gchar **) names); |
|
1716 } |
|
1717 |
|
1718 /** |
|
1719 * gst_plugin_add_dependency: |
|
1720 * @plugin: a #GstPlugin |
|
1721 * @env_vars: NULL-terminated array of environent variables affecting the |
|
1722 * feature set of the plugin (e.g. an environment variable containing |
|
1723 * paths where to look for additional modules/plugins of a library), |
|
1724 * or NULL. Environment variable names may be followed by a path component |
|
1725 * which will be added to the content of the environment variable, e.g. |
|
1726 * "HOME/.mystuff/plugins". |
|
1727 * @paths: NULL-terminated array of directories/paths where dependent files |
|
1728 * may be. |
|
1729 * @names: NULL-terminated array of file names (or file name suffixes, |
|
1730 * depending on @flags) to be used in combination with the paths from |
|
1731 * @paths and/or the paths extracted from the environment variables in |
|
1732 * @env_vars, or NULL. |
|
1733 * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE |
|
1734 * |
|
1735 * Make GStreamer aware of external dependencies which affect the feature |
|
1736 * set of this plugin (ie. the elements or typefinders associated with it). |
|
1737 * |
|
1738 * GStreamer will re-inspect plugins with external dependencies whenever any |
|
1739 * of the external dependencies change. This is useful for plugins which wrap |
|
1740 * other plugin systems, e.g. a plugin which wraps a plugin-based visualisation |
|
1741 * library and makes visualisations available as GStreamer elements, or a |
|
1742 * codec loader which exposes elements and/or caps dependent on what external |
|
1743 * codec libraries are currently installed. |
|
1744 * |
|
1745 * Since: 0.10.22 |
|
1746 */ |
|
1747 #ifdef __SYMBIAN32__ |
|
1748 EXPORT_C |
|
1749 #endif |
|
1750 |
|
1751 void |
|
1752 gst_plugin_add_dependency (GstPlugin * plugin, const gchar ** env_vars, |
|
1753 const gchar ** paths, const gchar ** names, GstPluginDependencyFlags flags) |
|
1754 { |
|
1755 GstPluginDep *dep; |
|
1756 GList *l; |
|
1757 |
|
1758 g_return_if_fail (GST_IS_PLUGIN (plugin)); |
|
1759 g_return_if_fail (env_vars != NULL || paths != NULL); |
|
1760 |
|
1761 for (l = plugin->priv->deps; l != NULL; l = l->next) { |
|
1762 if (gst_plugin_ext_dep_equals (l->data, env_vars, paths, names, flags)) { |
|
1763 GST_LOG_OBJECT (plugin, "dependency already registered"); |
|
1764 return; |
|
1765 } |
|
1766 } |
|
1767 |
|
1768 dep = g_new0 (GstPluginDep, 1); |
|
1769 |
|
1770 dep->env_vars = g_strdupv ((gchar **) env_vars); |
|
1771 dep->paths = g_strdupv ((gchar **) paths); |
|
1772 dep->names = g_strdupv ((gchar **) names); |
|
1773 dep->flags = flags; |
|
1774 |
|
1775 dep->env_hash = gst_plugin_ext_dep_get_env_vars_hash (plugin, dep); |
|
1776 dep->stat_hash = gst_plugin_ext_dep_get_stat_hash (plugin, dep); |
|
1777 |
|
1778 plugin->priv->deps = g_list_append (plugin->priv->deps, dep); |
|
1779 |
|
1780 GST_DEBUG_OBJECT (plugin, "added dependency:"); |
|
1781 for (; env_vars != NULL && *env_vars != NULL; ++env_vars) |
|
1782 GST_DEBUG_OBJECT (plugin, " evar: %s", *env_vars); |
|
1783 for (; paths != NULL && *paths != NULL; ++paths) |
|
1784 GST_DEBUG_OBJECT (plugin, " path: %s", *paths); |
|
1785 for (; names != NULL && *names != NULL; ++names) |
|
1786 GST_DEBUG_OBJECT (plugin, " name: %s", *names); |
|
1787 } |
|
1788 |
|
1789 /** |
|
1790 * gst_plugin_add_dependency_simple: |
|
1791 * @plugin: the #GstPlugin |
|
1792 * @env_vars: one or more environent variables (separated by ':', ';' or ','), |
|
1793 * or NULL. Environment variable names may be followed by a path component |
|
1794 * which will be added to the content of the environment variable, e.g. |
|
1795 * "HOME/.mystuff/plugins:MYSTUFF_PLUGINS_PATH" |
|
1796 * @paths: one ore more directory paths (separated by ':' or ';' or ','), |
|
1797 * or NULL. Example: "/usr/lib/mystuff/plugins" |
|
1798 * @names: one or more file names or file name suffixes (separated by commas), |
|
1799 * or NULL |
|
1800 * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE |
|
1801 * |
|
1802 * Make GStreamer aware of external dependencies which affect the feature |
|
1803 * set of this plugin (ie. the elements or typefinders associated with it). |
|
1804 * |
|
1805 * GStreamer will re-inspect plugins with external dependencies whenever any |
|
1806 * of the external dependencies change. This is useful for plugins which wrap |
|
1807 * other plugin systems, e.g. a plugin which wraps a plugin-based visualisation |
|
1808 * library and makes visualisations available as GStreamer elements, or a |
|
1809 * codec loader which exposes elements and/or caps dependent on what external |
|
1810 * codec libraries are currently installed. |
|
1811 * |
|
1812 * Convenience wrapper function for gst_plugin_add_dependency() which |
|
1813 * takes simple strings as arguments instead of string arrays, with multiple |
|
1814 * arguments separated by predefined delimiters (see above). |
|
1815 * |
|
1816 * Since: 0.10.22 |
|
1817 */ |
|
1818 #ifdef __SYMBIAN32__ |
|
1819 EXPORT_C |
|
1820 #endif |
|
1821 |
|
1822 void |
|
1823 gst_plugin_add_dependency_simple (GstPlugin * plugin, |
|
1824 const gchar * env_vars, const gchar * paths, const gchar * names, |
|
1825 GstPluginDependencyFlags flags) |
|
1826 { |
|
1827 gchar **a_evars = NULL; |
|
1828 gchar **a_paths = NULL; |
|
1829 gchar **a_names = NULL; |
|
1830 |
|
1831 if (env_vars) |
|
1832 a_evars = g_strsplit_set (env_vars, ":;,", -1); |
|
1833 if (paths) |
|
1834 a_paths = g_strsplit_set (paths, ":;,", -1); |
|
1835 if (names) |
|
1836 a_names = g_strsplit_set (names, ",", -1); |
|
1837 |
|
1838 gst_plugin_add_dependency (plugin, (const gchar **) a_evars, |
|
1839 (const gchar **) a_paths, (const gchar **) a_names, flags); |
|
1840 |
|
1841 if (a_evars) |
|
1842 g_strfreev (a_evars); |
|
1843 if (a_paths) |
|
1844 g_strfreev (a_paths); |
|
1845 if (a_names) |
|
1846 g_strfreev (a_names); |
|
1847 } |
|