sbGStreamerMediacoreFactory.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
28 
29 #include <nsMemory.h>
30 
31 #include <nsXPCOMCID.h>
32 #include <nsIObserverService.h>
33 #include <nsIPrefBranch.h>
34 #include <nsIPrefService.h>
35 
38 
39 #include <sbIGStreamerService.h>
40 #include <sbStringUtils.h>
41 
42 #include "sbGStreamerMediacore.h"
44 
51 #ifdef PR_LOGGING
52 
53 static PRLogModuleInfo* gGStreamerMediacoreFactory =
54  PR_NewLogModule("sbGStreamerMediacoreFactory");
55 
56 #define LOG(args) \
57  if (gGStreamerMediacoreFactory) \
58  PR_LOG(gGStreamerMediacoreFactory, PR_LOG_WARNING, args)
59 
60 #define TRACE(args) \
61  if (gGStreamerMediacoreFactory) \
62  PR_LOG(gGStreamerMediacoreFactory, PR_LOG_DEBUG, args)
63 
64 #else /* PR_LOGGING */
65 
66 #define LOG(args) /* nothing */
67 #define TRACE(args) /* nothing */
68 
69 #endif /* PR_LOGGING */
70 
71 #define BLACKLIST_EXTENSIONS_PREF "songbird.mediacore.gstreamer.blacklistExtensions"
72 #define VIDEO_EXTENSIONS_PREF "songbird.mediacore.gstreamer.videoExtensions"
73 #define VIDEO_DISABLED_PREF "songbird.mediacore.gstreamer.disablevideo"
74 
79 
82 
83 sbGStreamerMediacoreFactory::sbGStreamerMediacoreFactory()
84 {
85 }
86 
88 {
89 
90 }
91 
92 nsresult
94 {
96  NS_ENSURE_SUCCESS(rv, rv);
97 
98  /* Ensure GStreamer has been loaded by getting the gstreamer service
99  * component (which loads and initialises gstreamer for us).
100  */
101  nsCOMPtr<sbIGStreamerService> service =
102  do_GetService(SBGSTREAMERSERVICE_CONTRACTID, &rv);
103  NS_ENSURE_SUCCESS(rv, rv);
104 
105  nsCOMPtr<nsIObserverService> obs =
106  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
107  NS_ENSURE_SUCCESS(rv, rv);
108 
109  rv = obs->AddObserver(this, "quit-application", PR_FALSE);
110  NS_ENSURE_SUCCESS(rv, rv);
111 
112  nsCOMPtr<nsIPrefBranch2> rootPrefBranch =
113  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
114  NS_ENSURE_SUCCESS(rv, rv);
115 
116  rv = rootPrefBranch->AddObserver(BLACKLIST_EXTENSIONS_PREF, this, PR_FALSE);
117  NS_ENSURE_SUCCESS(rv, rv);
118 
119  rv = rootPrefBranch->AddObserver(VIDEO_EXTENSIONS_PREF, this, PR_FALSE);
120  NS_ENSURE_SUCCESS(rv, rv);
121 
122  return NS_OK;
123 }
124 
125 /*virtual*/ nsresult
127 {
128  nsresult rv;
129 
130  nsCOMPtr<nsIObserverService> obs =
131  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
132  NS_ENSURE_SUCCESS(rv, rv);
133 
134  rv = obs->RemoveObserver(this, "quit-application");
135  NS_ENSURE_SUCCESS(rv, rv);
136 
137  nsCOMPtr<nsIPrefBranch2> rootPrefBranch =
138  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
139  NS_ENSURE_SUCCESS(rv, rv);
140 
141  rv = rootPrefBranch->RemoveObserver(BLACKLIST_EXTENSIONS_PREF, this);
142  NS_ENSURE_SUCCESS(rv, rv);
143 
144  rv = rootPrefBranch->RemoveObserver(VIDEO_EXTENSIONS_PREF, this);
145  NS_ENSURE_SUCCESS(rv, rv);
146 
147  return NS_OK;
148 }
149 
150 /*virtual*/ nsresult
152 {
153  nsresult rv =
155  NS_ENSURE_SUCCESS(rv, rv);
156 
157  rv =
159  NS_ENSURE_SUCCESS(rv, rv);
160 
161  return NS_OK;
162 }
163 
164 /*virtual*/ nsresult
166  sbIMediacoreCapabilities **aCapabilities)
167 {
168  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
169  nsAutoMonitor mon(mMonitor);
170 
171  // TODO: This function is now a _huge_ mess. We should talk to product about
172  // what files we want to import / etc, some time soon - e.g. the current
173  // approach is to treat anything even vaguely-plausibly audio-related as
174  // audio (even if we can't play it!), but to only import a small list of fixed
175  // extensions for videos (excluding many things we might be able to play).
176 
177  nsresult rv;
178  if (!mCapabilities) {
179  nsRefPtr<sbMediacoreCapabilities> caps;
180  NS_NEWXPCOM(caps, sbMediacoreCapabilities);
181  NS_ENSURE_TRUE(caps, NS_ERROR_OUT_OF_MEMORY);
182 
183  rv = caps->Init();
184  NS_ENSURE_SUCCESS(rv, rv);
185 
186  // Build a big list of extensions based on everything gstreamer knows about,
187  // plus some known ones, minus a few known non-media-file extensions that
188  // gstreamer has typefinders for.
189 
190  nsCOMPtr<nsIPrefBranch> rootPrefBranch =
191  do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
192  NS_ENSURE_SUCCESS(rv, rv);
193 
194  nsTArray<nsString> audioExtensions;
195  nsTArray<nsString> videoExtensions;
196 
197  // XXX Mook: we have a silly list of blacklisted extensions because we don't
198  // support them and we're being stupid and guessing things based on them.
199  // This crap should really look for a plugin that may possibly actually decode
200  // these things, or something better. Whatever the real solution is, this
201  // isn't it :(
202  nsCString blacklistExtensions;
203  { // for scope
204  const char defaultBlacklistExtensions[] =
205  "txt,htm,html,xml,pdf,cpl,msstyles,scr,sys,ocx,bz2,gz,zip,Z,rar,tar,dll,"
206  "exe,a,bmp,png,gif,jpeg,jpg,jpe,tif,tiff,xpm,dat,swf,swfl,stm,cgi,sf,xcf,"
207  "far,wvc,mpc,mpp,mp+,ra,rm,rmvb";
208  char* blacklistExtensionsPtr = nsnull;
209  rv = rootPrefBranch->GetCharPref(BLACKLIST_EXTENSIONS_PREF,
210  &blacklistExtensionsPtr);
211  if (NS_SUCCEEDED(rv)) {
212  blacklistExtensions.Adopt(blacklistExtensionsPtr);
213  } else {
214  blacklistExtensions.Assign(defaultBlacklistExtensions);
215  }
216  blacklistExtensions.Insert(',', 0);
217  blacklistExtensions.Append(',');
218  LOG(("sbGStreamerMediacoreFactory: blacklisted extensions: %s\n",
219  blacklistExtensions.BeginReading()));
220  }
221 
222  const char *extraAudioExtensions[] = {"m4r", "m4p", "oga",
223  "ogg", "aac", "3gp"};
224 #if defined(XP_WIN) || defined(XP_UNIX)
225  const char *extraWindowsAudioExtensions[] = {"wma" };
226 #endif
227 
228  { // for scope
229 
230  // Per bug 19550 -
231  // Severly limit the video extensions that are imported by default to:
232  // * ogv (all platforms)
233  // * wmv (windows only)
234  // * mp4/m4v/mov (w/ qtvideowrapper plugin)
235 
236  // Story 25411567
237  // ewmpeg4dec plugin is no more, so allow divx/avi/mkv unconditionally
238  // PLUS VOB
239 
240  videoExtensions.AppendElement(NS_LITERAL_STRING("ogv"));
241  videoExtensions.AppendElement(NS_LITERAL_STRING("ogx"));
242  videoExtensions.AppendElement(NS_LITERAL_STRING("divx"));
243  videoExtensions.AppendElement(NS_LITERAL_STRING("avi"));
244  videoExtensions.AppendElement(NS_LITERAL_STRING("mkv"));
245  videoExtensions.AppendElement(NS_LITERAL_STRING("vob"));
246  // must allow mpg/mpeg unconditionally, support is duplicated
247  // in windowsmedia plugin but is expected to be importable on Mac too
248  videoExtensions.AppendElement(NS_LITERAL_STRING("mpg"));
249  videoExtensions.AppendElement(NS_LITERAL_STRING("mpeg"));
250 
251 #ifdef XP_WIN
252  videoExtensions.AppendElement(NS_LITERAL_STRING("wmv"));
253 #endif
254 
255  char* knownVideoExtensionsPtr = nsnull;
256  rv = rootPrefBranch->GetCharPref(VIDEO_EXTENSIONS_PREF,
257  &knownVideoExtensionsPtr);
258  if (NS_SUCCEEDED(rv)) {
259  // The override video extension pref contains a CSV string.
260  nsString_Split(NS_ConvertUTF8toUTF16(knownVideoExtensionsPtr),
261  NS_LITERAL_STRING(","),
262  videoExtensions);
263  }
264 
265 #ifdef PR_LOGGING
266  nsString videoExtensionStr;
267  for (PRUint32 i = 0; i < videoExtensions.Length(); i++) {
268  videoExtensionStr.Append(videoExtensions[i]);
269  if (i < videoExtensions.Length() - 1) {
270  videoExtensionStr.AppendLiteral(", ");
271  }
272  }
273 
274  LOG(("sbGStreamerMediacoreFactory: video file extensions: %s\n",
275  videoExtensionStr.get()));
276 #endif
277 
278  // Check for the 'qtvideowrapper' plugin to add mp4/m4v extensions.
279  GstPlugin *plugin = gst_default_registry_find_plugin("qtvideowrapper");
280  if (plugin) {
281  videoExtensions.AppendElement(NS_LITERAL_STRING("mp4"));
282  videoExtensions.AppendElement(NS_LITERAL_STRING("m4v"));
283  videoExtensions.AppendElement(NS_LITERAL_STRING("mov"));
284  gst_object_unref(plugin);
285  }
286  }
287 
288  GList *walker, *list;
289 
290  list = gst_type_find_factory_get_list ();
291  walker = list;
292  while (walker) {
293  GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walker->data);
294  gboolean blacklisted = FALSE;
295  const gchar* factoryName = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory));
296  gboolean isAudioFactory = g_str_has_prefix(factoryName, "audio/");
297 
298  gchar **factoryexts = gst_type_find_factory_get_extensions (factory);
299  if (factoryexts) {
300  while (*factoryexts) {
301  gboolean isAudioExtension = isAudioFactory;
302  nsCString extension(*factoryexts);
303  nsCString delimitedExtension(extension);
304  delimitedExtension.Insert(',', 0);
305  delimitedExtension.Append(',');
306 
307  blacklisted = (blacklistExtensions.Find(delimitedExtension) != -1);
308  #if PR_LOGGING
309  if (blacklisted) {
310  LOG(("sbGStreamerMediacoreFactory: Ignoring extension '%s'", *factoryexts));
311  }
312  #endif /* PR_LOGGING */
313 
314  if (!blacklisted && isAudioExtension) {
315  audioExtensions.AppendElement(NS_ConvertUTF8toUTF16(*factoryexts));
316  LOG(("sbGStreamerMediacoreFactory: registering audio extension %s\n",
317  *factoryexts));
318  }
319 
320  factoryexts++;
321  }
322  }
323  walker = g_list_next (walker);
324  }
325  g_list_free (list);
326 
327  for (unsigned int i = 0; i < NS_ARRAY_LENGTH(extraAudioExtensions); i++) {
328  nsString ext = NS_ConvertUTF8toUTF16(extraAudioExtensions[i]);
329  if(!audioExtensions.Contains(ext))
330  audioExtensions.AppendElement(ext);
331  }
332 
333 #if defined(XP_WIN) || defined(XP_UNIX)
334  for (unsigned int i = 0; i < NS_ARRAY_LENGTH(extraWindowsAudioExtensions); i++) {
335  nsString ext = NS_ConvertUTF8toUTF16(extraWindowsAudioExtensions[i]);
336  if(!audioExtensions.Contains(ext))
337  audioExtensions.AppendElement(ext);
338  }
339 #endif
340 
341  rv = caps->SetAudioExtensions(audioExtensions);
342  NS_ENSURE_SUCCESS(rv, rv);
343 
344  // Audio playback is always allowed.
345  rv = caps->SetSupportsAudioPlayback(PR_TRUE);
346  NS_ENSURE_SUCCESS(rv, rv);
347 
348  PRBool videoDisabled = PR_FALSE;
349  rv = rootPrefBranch->GetBoolPref(
350  "songbird.mediacore.gstreamer.disablevideo",
351  &videoDisabled);
352  NS_ENSURE_SUCCESS(rv, rv);
353  if (!videoDisabled) {
354  rv = caps->SetVideoExtensions(videoExtensions);
355  NS_ENSURE_SUCCESS(rv, rv);
356 
357  rv = caps->SetSupportsVideoPlayback(PR_TRUE);
358  NS_ENSURE_SUCCESS(rv, rv);
359  }
360 
361  mCapabilities = caps;
362  }
363 
364  rv = CallQueryInterface(mCapabilities.get(), aCapabilities);
365  NS_ENSURE_SUCCESS(rv, rv);
366 
367  return NS_OK;
368 }
369 
370 /*virtual*/ nsresult
371 sbGStreamerMediacoreFactory::OnCreate(const nsAString &aInstanceName,
372  sbIMediacore **_retval)
373 {
374  nsRefPtr<sbGStreamerMediacore> mediacore;
375  NS_NEWXPCOM(mediacore, sbGStreamerMediacore);
376  NS_ENSURE_TRUE(mediacore, NS_ERROR_OUT_OF_MEMORY);
377 
378  nsresult rv = mediacore->Init();
379  NS_ENSURE_SUCCESS(rv, rv);
380 
381  rv = mediacore->SetInstanceName(aInstanceName);
382  NS_ENSURE_SUCCESS(rv, rv);
383 
384  rv = CallQueryInterface(mediacore.get(), _retval);
385  NS_ENSURE_SUCCESS(rv, rv);
386 
387  return NS_OK;
388 }
389 
390 nsresult
391 sbGStreamerMediacoreFactory::Observe(nsISupports *subject,
392  const char* topic,
393  const PRUnichar *aData)
394 {
395  if (!strcmp(topic, "quit-application")) {
396  return Shutdown();
397  }
398  else if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
399  NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED);
400  nsAutoMonitor mon(mMonitor);
401 
402  mCapabilities = nsnull;
403  return NS_OK;
404  }
405 
406  return NS_OK;
407 }
#define BLACKLIST_EXTENSIONS_PREF
return NS_OK
nsresult SetContractID(const nsAString &aContractID)
id service()
const NS_PREFSERVICE_CONTRACTID
virtual nsresult OnCreate(const nsAString &aInstanceName, sbIMediacore **_retval)
nsresult SetName(const nsAString &aName)
#define SB_MEDIACORE_FACTORY_REGISTERSELF_IMPL(_name, _desc)
#define SB_GSTREAMERMEDIACOREFACTORY_DESCRIPTION
#define SBGSTREAMERSERVICE_CONTRACTID
Songbird Mediacore Capabilities Definition.
void nsString_Split(const nsAString &aString, const nsAString &aDelimiter, nsTArray< nsString > &aSubStringArray)
#define LOG(args)
NS_IMPL_ISUPPORTS_INHERITED2(sbGStreamerMediacoreFactory, sbBaseMediacoreFactory, sbIMediacoreFactory, nsIObserver) SB_MEDIACORE_FACTORY_REGISTERSELF_IMPL(sbGStreamerMediacoreFactory
virtual nsresult OnGetCapabilities(sbIMediacoreCapabilities **aCapabilities)
#define VIDEO_EXTENSIONS_PREF
#define SB_GSTREAMERMEDIACOREFACTORY_CONTRACTID
nsRefPtr< sbMediacoreCapabilities > mCapabilities
observe topic
Definition: FeedWriter.js:1326
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
_getSelectedPageStyle s i
_updateTextAndScrollDataForFrame aData