27 #include <gst/pbutils/descriptions.h>
32 #include <nsIEnvironment.h>
33 #include <nsIProperties.h>
35 #include <nsILocalFile.h>
36 #include <nsStringGlue.h>
39 #include <nsServiceManagerUtils.h>
40 #include <nsDirectoryServiceUtils.h>
41 #include <nsAppDirectoryServiceDefs.h>
42 #include <nsComponentManagerUtils.h>
43 #include <nsThreadUtils.h>
44 #include <nsXULAppAPI.h>
45 #include <nsISimpleEnumerator.h>
46 #include <nsIPrefBranch.h>
54 #define GSTREAMER_COMPREG_LAST_MODIFIED_TIME_PREF \
55 "songbird.mediacore.gstreamer.compreg_last_modified_time"
65 static PRLogModuleInfo* gGStreamerService =
66 PR_NewLogModule(
"sbGStreamerService");
69 if (gGStreamerService) \
70 PR_LOG(gGStreamerService, PR_LOG_WARNING, args)
73 if (gGStreamerService) \
74 PR_LOG(gGStreamerService, PR_LOG_DEBUG, args)
89 case GST_RANK_MARGINAL:
91 case GST_RANK_SECONDARY:
93 case GST_RANK_PRIMARY:
104 LOG((
"sbGStreamerService[0x%.8x] - ctor",
this));
107 sbGStreamerService::~sbGStreamerService()
109 LOG((
"sbGStreamerService[0x%.8x] - dtor",
this));
123 if (aValue.IsVoid()) {
124 result = ::SetEnvironmentVariableW(PromiseFlatString(aName).
get(), NULL);
126 result = ::SetEnvironmentVariableW(PromiseFlatString(aName).
get(),
127 PromiseFlatString(aValue).
get());
129 return (result != 0) ?
NS_OK : NS_ERROR_FAILURE;
132 CopyUTF16toUTF8(aName, env);
133 env.AppendLiteral(
"=");
134 env.Append(NS_ConvertUTF16toUTF8(aValue));
135 PRInt32 length = env.Length();
136 char* buf = (
char*)NS_Alloc(length + 1);
138 return NS_ERROR_OUT_OF_MEMORY;
140 memcpy(buf, env.get(), length);
142 PRStatus status = PR_SetEnv(buf);
144 return (PR_SUCCESS == status) ?
NS_OK : NS_ERROR_FAILURE;
152 NS_ASSERTION(NS_IsMainThread(),
"Not on main thread");
155 NS_NAMED_LITERAL_STRING(kGstPluginSystemPath,
"GST_PLUGIN_SYSTEM_PATH");
156 NS_NAMED_LITERAL_STRING(kGstRegistry,
"GST_REGISTRY");
157 NS_NAMED_LITERAL_STRING(kGstPluginPath,
"GST_PLUGIN_PATH");
158 PRBool noSystemPlugins;
161 PRBool
first = PR_TRUE;
162 nsString pluginPaths;
163 nsString systemPluginPaths;
165 nsCOMPtr<nsISimpleEnumerator> dirList;
167 nsCOMPtr<nsIEnvironment> envSvc =
168 do_GetService(
"@mozilla.org/process/environment;1", &rv);
169 NS_ENSURE_SUCCESS(rv, rv);
171 nsCOMPtr<nsIProperties> directorySvc =
172 do_GetService(
"@mozilla.org/file/directory_service;1", &rv);
173 NS_ENSURE_SUCCESS(rv, rv);
175 #if defined(XP_MACOSX) || defined(XP_WIN)
176 systemGst = PR_FALSE;
177 noSystemPlugins = PR_TRUE;
182 rv = envSvc->Exists(NS_LITERAL_STRING(
"SB_GST_SYSTEM"), &systemGst);
183 NS_ENSURE_SUCCESS(rv, rv);
185 rv = envSvc->Exists(NS_LITERAL_STRING(
"SB_GST_NO_SYSTEM"), &noSystemPlugins);
186 NS_ENSURE_SUCCESS(rv, rv);
204 #if defined(XP_MACOSX) || defined(XP_WIN)
205 pluginPaths = EmptyString();
208 PRBool pluginPathExists;
209 rv = envSvc->Exists(kGstPluginPath, &pluginPathExists);
210 NS_ENSURE_SUCCESS(rv, rv);
211 if (pluginPathExists) {
212 rv = envSvc->Get(kGstPluginPath, pluginPaths);
213 NS_ENSURE_SUCCESS(rv, rv);
217 pluginPaths = EmptyString();
222 nsCOMPtr<nsIFile> pluginDir;
223 rv = directorySvc->Get(
"resource:app",
225 getter_AddRefs(pluginDir));
226 NS_ENSURE_SUCCESS(rv, rv);
228 rv = pluginDir->Append(NS_LITERAL_STRING(
"gst-plugins"));
229 NS_ENSURE_SUCCESS(rv, rv);
231 nsString pluginDirStr;
232 rv = pluginDir->GetPath(pluginDirStr);
233 NS_ENSURE_SUCCESS(rv, rv);
236 pluginPaths.AppendLiteral(G_SEARCHPATH_SEPARATOR_S);
237 pluginPaths.Append(pluginDirStr);
239 LOG((
"sbGStreamerService[0x%.8x] - Setting GST_PLUGIN_PATH=%s",
this,
240 NS_LossyConvertUTF16toASCII(pluginPaths).
get()));
241 rv =
SetEnvVar(kGstPluginPath, pluginPaths);
242 NS_ENSURE_SUCCESS(rv, rv);
247 rv = directorySvc->Get(XRE_EXTENSIONS_DIR_LIST,
249 getter_AddRefs(dirList));
250 NS_ENSURE_SUCCESS(rv, rv);
252 while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
254 nsCOMPtr<nsISupports> supports;
255 rv = dirList->GetNext(getter_AddRefs(supports));
258 nsCOMPtr<nsIFile> extensionDir(do_QueryInterface(supports, &rv));
262 rv = extensionDir->Append(NS_LITERAL_STRING(
"gst-plugins"));
263 NS_ENSURE_SUCCESS(rv, rv);
264 rv = extensionDir->Exists(&dirExists);
265 NS_ENSURE_SUCCESS(rv, rv);
269 rv = extensionDir->GetPath(dirPath);
270 NS_ENSURE_SUCCESS(rv, rv);
273 pluginPaths.AppendLiteral(G_SEARCHPATH_SEPARATOR_S);
274 pluginPaths.Append(dirPath);
281 nsCOMPtr<nsIFile> dependencyListFile;
282 rv = extensionDir->Clone(getter_AddRefs(dependencyListFile));
283 NS_ENSURE_SUCCESS(rv, rv);
285 rv = dependencyListFile->Append(
286 NS_LITERAL_STRING(
"dependent-libraries.txt"));
287 NS_ENSURE_SUCCESS(rv, rv);
289 rv = dependencyListFile->Exists(&fileExists);
290 NS_ENSURE_SUCCESS(rv, rv);
294 NS_ENSURE_SUCCESS(rv, rv);
300 nsCOMPtr<nsIFile> pluginDir;
301 rv = directorySvc->Get(
"resource:app",
303 getter_AddRefs(pluginDir));
304 NS_ENSURE_SUCCESS(rv, rv);
306 rv = pluginDir->Append(NS_LITERAL_STRING(
"gst-plugins"));
307 NS_ENSURE_SUCCESS(rv, rv);
309 nsString pluginDirStr;
310 rv = pluginDir->GetPath(pluginDirStr);
311 NS_ENSURE_SUCCESS(rv, rv);
314 pluginPaths.AppendLiteral(G_SEARCHPATH_SEPARATOR_S);
315 pluginPaths.Append(pluginDirStr);
318 #if !defined(XP_MACOSX) && !defined(XP_WIN)
320 if (!noSystemPlugins) {
324 char *homeDirPlugins = g_build_filename (g_get_home_dir (),
325 ".gstreamer-0.10",
"plugins", NULL);
326 systemPluginPaths = NS_ConvertUTF8toUTF16(homeDirPlugins);
335 nsCOMPtr<nsILocalFile> badFile = do_CreateInstance(
336 "@mozilla.org/file/local;1", &rv);
337 NS_ENSURE_SUCCESS(rv, rv);
341 sysLibDir = NS_LITERAL_STRING(
"/usr/lib64/gstreamer-0.10");
343 sysLibDir = NS_LITERAL_STRING(
"/usr/lib/gstreamer-0.10");
346 nsString badFilePath = sysLibDir;
347 badFilePath.AppendLiteral(
"/libgsturidecodebin.so");
349 rv = badFile->InitWithPath(badFilePath);
350 NS_ENSURE_SUCCESS(rv, rv);
352 PRBool badFileExists;
353 rv = badFile->Exists(&badFileExists);
354 NS_ENSURE_SUCCESS(rv, rv);
356 if (!badFileExists) {
357 systemPluginPaths.AppendLiteral(G_SEARCHPATH_SEPARATOR_S);
358 systemPluginPaths.Append(sysLibDir);
362 systemPluginPaths = NS_LITERAL_STRING(
"");
363 #endif // !defined(XP_MACOSX) && !defined(XP_WIN)
366 LOG((
"sbGStreamerService[0x%.8x] - Setting GST_PLUGIN_PATH=%s",
this,
367 NS_LossyConvertUTF16toASCII(pluginPaths).
get()));
368 rv =
SetEnvVar(kGstPluginPath, pluginPaths);
369 NS_ENSURE_SUCCESS(rv, rv);
371 LOG((
"sbGStreamerService[0x%.8x] - Setting GST_PLUGIN_SYSTEM_PATH=%s",
this,
372 NS_LossyConvertUTF16toASCII(systemPluginPaths).
get()));
373 rv =
SetEnvVar(kGstPluginSystemPath, systemPluginPaths);
374 NS_ENSURE_SUCCESS(rv, rv);
379 nsCOMPtr<nsIFile> registryPath;
380 rv = GetGStreamerRegistryFile(getter_AddRefs(registryPath));
381 NS_ENSURE_SUCCESS(rv, rv);
383 nsString registryPathStr;
384 rv = registryPath->GetPath(registryPathStr);
385 NS_ENSURE_SUCCESS(rv, rv);
387 LOG((
"sbGStreamerService[0x%.8x] - Setting GST_REGISTRY=%s",
this,
388 NS_LossyConvertUTF16toASCII(registryPathStr).
get()));
390 rv =
SetEnvVar(kGstRegistry, registryPathStr);
391 NS_ENSURE_SUCCESS(rv, rv);
398 gst_registry_fork_set_enabled(FALSE);
402 UpdateGStreamerRegistryFile();
404 gst_init(NULL, NULL);
415 NS_ENSURE_ARG_POINTER(aHandler);
418 char libvisual[10] =
"libvisual";
420 GList *plugins, *orig_plugins;
422 rv = aHandler->BeginInspect();
423 NS_ENSURE_SUCCESS(rv, rv);
425 orig_plugins = plugins = gst_default_registry_get_plugin_list();
428 plugin = (GstPlugin *) (plugins->data);
429 plugins = g_list_next (plugins);
431 if (g_strcmp0(plugin->desc.name, libvisual) != 0) {
434 if (plugin->filename) {
435 filename = plugin->filename;
438 filename.SetIsVoid(PR_TRUE);
441 rv = aHandler->BeginPluginInfo(nsDependentCString(plugin->desc.name),
442 nsDependentCString(plugin->desc.description),
444 nsDependentCString(plugin->desc.version),
445 nsDependentCString(plugin->desc.license),
446 nsDependentCString(plugin->desc.source),
447 nsDependentCString(plugin->desc.package),
448 nsDependentCString(plugin->desc.origin));
449 NS_ENSURE_SUCCESS(rv, rv);
451 GList *features, *orig_features;
452 orig_features = features =
453 gst_registry_get_feature_list_by_plugin(gst_registry_get_default(),
456 GstPluginFeature *feature;
457 feature = GST_PLUGIN_FEATURE(features->data);
459 if (g_strcmp0(feature->plugin_name, libvisual) != 0) {
460 if (GST_IS_ELEMENT_FACTORY(feature)) {
461 GstElementFactory *factory;
462 factory = GST_ELEMENT_FACTORY(feature);
464 rv = InspectFactory(factory, aHandler);
465 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"InspectFactory failed");
468 LOG((
"sbGStreamerService[0x%.8x] - Caught libvisual",
this));
471 features = g_list_next(features);
474 gst_plugin_feature_list_free(orig_features);
476 rv = aHandler->EndPluginInfo();
477 NS_ENSURE_SUCCESS(rv, rv);
481 gst_plugin_list_free(orig_plugins);
483 rv = aHandler->EndInspect();
484 NS_ENSURE_SUCCESS(rv, rv);
490 sbGStreamerService::InspectFactory(GstElementFactory* aFactory,
495 GstElementFactory* factory;
497 GST_ELEMENT_FACTORY(gst_plugin_feature_load(GST_PLUGIN_FEATURE
499 NS_ENSURE_TRUE(factory, NS_ERROR_UNEXPECTED);
502 element = gst_element_factory_create(aFactory, NULL);
503 NS_ENSURE_TRUE(element, NS_ERROR_UNEXPECTED);
505 gint rank = GST_PLUGIN_FEATURE(factory)->rank;
507 rv = aHandler->BeginFactoryInfo(nsDependentCString(GST_PLUGIN_FEATURE(factory)->
name),
508 nsDependentCString(factory->details.longname),
509 nsDependentCString(factory->details.klass),
510 nsDependentCString(factory->details.description),
511 nsDependentCString(factory->details.author),
514 NS_ENSURE_SUCCESS(rv, rv);
516 rv = InspectFactoryPads(element, factory, aHandler);
517 NS_ENSURE_SUCCESS(rv, rv);
519 rv = aHandler->EndFactoryInfo();
520 NS_ENSURE_SUCCESS(rv, rv);
526 sbGStreamerService::InspectFactoryPads(GstElement* aElement,
527 GstElementFactory* aFactory,
530 GstElementClass *gstelement_class;
531 gstelement_class = GST_ELEMENT_CLASS(G_OBJECT_GET_CLASS(aElement));
535 pads = aFactory->staticpadtemplates;
537 GstStaticPadTemplate *padtemplate;
538 padtemplate = (GstStaticPadTemplate *) (pads->data);
539 pads = g_list_next(pads);
542 switch (padtemplate->direction) {
554 switch (padtemplate->presence) {
558 case GST_PAD_SOMETIMES:
565 nsCString codecDescription;
567 GstCaps* caps = gst_static_caps_get(&padtemplate->static_caps);
569 if (gst_caps_is_fixed(caps)) {
570 gchar* codec = gst_pb_utils_get_codec_description(caps);
572 codecDescription = codec;
575 gst_caps_unref(caps);
579 if (codecDescription.IsEmpty()) {
580 codecDescription.SetIsVoid(PR_TRUE);
582 rv = aHandler->BeginPadTemplateInfo(nsDependentCString(padtemplate->name_template),
586 NS_ENSURE_SUCCESS(rv, rv);
588 rv = aHandler->EndPadTemplateInfo();
589 NS_ENSURE_SUCCESS(rv, rv);
596 sbGStreamerService::UpdateGStreamerRegistryFile()
601 nsCOMPtr<nsIFile> mozRegFile;
603 getter_AddRefs(mozRegFile));
604 NS_ENSURE_SUCCESS(rv, rv);
605 rv = mozRegFile->Append(NS_LITERAL_STRING(
"compreg.dat"));
606 NS_ENSURE_SUCCESS(rv, rv);
610 rv = mozRegFile->Exists(&exists);
611 NS_ENSURE_SUCCESS(rv, rv);
614 nsCAutoString lastModifiedTime;
616 PRInt64 lastModifiedTime64;
617 rv = mozRegFile->GetLastModifiedTime(&lastModifiedTime64);
618 NS_ENSURE_SUCCESS(rv, rv);
619 lastModifiedTime.Assign(NS_ConvertUTF16toUTF8
625 nsCAutoString lastModifiedTimePref;
626 nsCOMPtr<nsIPrefBranch>
627 prefBranch = do_GetService(
"@mozilla.org/preferences-service;1", &rv);
628 NS_ENSURE_SUCCESS(rv, rv);
630 getter_Copies(lastModifiedTimePref));
636 if (lastModifiedTimePref.IsEmpty() ||
637 !lastModifiedTimePref.Equals(lastModifiedTime)) {
638 nsCOMPtr<nsIFile> gstreamerRegFile;
639 rv = GetGStreamerRegistryFile(getter_AddRefs(gstreamerRegFile));
640 NS_ENSURE_SUCCESS(rv, rv);
641 rv = gstreamerRegFile->Exists(&exists);
642 NS_ENSURE_SUCCESS(rv, rv);
644 rv = gstreamerRegFile->Remove(PR_FALSE);
645 NS_ENSURE_SUCCESS(rv, rv);
651 lastModifiedTime.get());
652 NS_ENSURE_SUCCESS(rv, rv);
658 sbGStreamerService::GetGStreamerRegistryFile(nsIFile **aOutRegistryFile)
660 NS_ENSURE_ARG_POINTER(aOutRegistryFile);
661 *aOutRegistryFile = nsnull;
664 nsCOMPtr<nsIProperties> directorySvc =
665 do_GetService(
"@mozilla.org/file/directory_service;1", &rv);
666 NS_ENSURE_SUCCESS(rv, rv);
668 nsCOMPtr<nsIFile> registryPath;
671 getter_AddRefs(registryPath));
672 NS_ENSURE_SUCCESS(rv, rv);
674 rv = registryPath->Append(NS_LITERAL_STRING(
"gstreamer-0.10"));
675 NS_ENSURE_SUCCESS(rv, rv);
676 rv = registryPath->Append(NS_LITERAL_STRING(
"registry.bin"));
677 NS_ENSURE_SUCCESS(rv, rv);
679 registryPath.forget(aOutRegistryFile);
const unsigned long PAD_PRESENCE_SOMETIMES
static nsresult SB_LoadLibraries(nsIFile *aManifest)
const unsigned long PAD_DIRECTION_SINK
const unsigned long PAD_PRESENCE_REQUEST
const unsigned long PAD_PRESENCE_ALWAYS
NS_IMPL_THREADSAFE_ISUPPORTS1(sbDeviceCapsCompatibility, sbIDeviceCapsCompatibility) sbDeviceCapsCompatibility
nsresult SetEnvVar(const nsAString &aName, const nsAString &aValue)
const unsigned long PAD_DIRECTION_SRC
StringArrayEnumerator prototype hasMore
NS_DECL_ISUPPORTS NS_DECL_SBIGSTREAMERSERVICE nsresult Init()
static const char * get_rank_name(gint rank)
#define GSTREAMER_COMPREG_LAST_MODIFIED_TIME_PREF
const unsigned long PAD_DIRECTION_UNKNOWN