sbTranscodeProfileLoader.cpp
Go to the documentation of this file.
1 /* vim: set sw=2 : */
2 /*
3 //
4 // BEGIN SONGBIRD GPL
5 //
6 // This file is part of the Songbird web player.
7 //
8 // Copyright(c) 2005-2009 POTI, Inc.
9 // http://songbirdnest.com
10 //
11 // This file may be licensed under the terms of of the
12 // GNU General Public License Version 2 (the "GPL").
13 //
14 // Software distributed under the License is distributed
15 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
16 // express or implied. See the GPL for the specific language
17 // governing rights and limitations.
18 //
19 // You should have received a copy of the GPL along with this
20 // program. If not, go to http://www.gnu.org/licenses/gpl.html
21 // or write to the Free Software Foundation, Inc.,
22 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //
24 // END SONGBIRD GPL
25 //
26 */
27 
29 
30 #include <nsIDOM3Node.h>
31 #include <nsIDOMDocument.h>
32 #include <nsIDOMElement.h>
33 #include <nsIDOMNode.h>
34 #include <nsIDOMParser.h>
35 #include <nsIFile.h>
36 #include <nsIFileStreams.h>
37 #include <nsIMutableArray.h>
38 
39 #include <nsAutoPtr.h>
40 #include <nsCOMPtr.h>
41 #include <nsComponentManagerUtils.h>
42 #include <nsStringGlue.h>
43 #include <nsThreadUtils.h>
44 #include <prdtoa.h>
45 
46 #include <sbVariantUtils.h>
47 
48 #include "sbTranscodeProfile.h"
51 
54  nsIRunnable);
55 
57 {
58 }
59 
60 sbTranscodeProfileLoader::~sbTranscodeProfileLoader()
61 {
62 }
63 
64 /* sbITranscodeProfile loadProfile (in nsIFile aFile); */
65 NS_IMETHODIMP
66 sbTranscodeProfileLoader::LoadProfile(nsIFile *aFile,
67  sbITranscodeProfile **_retval)
68 {
69  NS_ENSURE_ARG_POINTER(_retval);
70 
71  nsresult rv;
72 
73  mFile = aFile;
74  if (NS_IsMainThread()) {
75  // this is on the main thread, call directly
76  rv = LoadProfileInternal();
77  NS_ENSURE_SUCCESS(rv, rv);
78 
79  rv = CallQueryInterface(mProfile.get(), _retval);
80  NS_ENSURE_SUCCESS(rv, rv);
81 
82  mProfile = nsnull;
83  }
84  else {
85  nsCOMPtr<nsIRunnable> runnable =
86  do_QueryInterface(NS_ISUPPORTS_CAST(nsIRunnable*, this), &rv);
87  NS_ASSERTION(runnable, "sbTranscodeProfileLoader should implement nsIRunnable");
88  rv = NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC);
89  NS_ENSURE_SUCCESS(rv, rv);
90 
91  rv = CallQueryInterface(mProfile.get(), _retval);
92  NS_ENSURE_SUCCESS(rv, rv);
93 
94  mProfile = nsnull;
95 
96  // check the return value from LoadProfileInternal
97  NS_ENSURE_SUCCESS(mResult, mResult);
98  }
99 
100  mFile = nsnull;
101  return NS_OK;
102 }
103 
105 NS_IMETHODIMP
106 sbTranscodeProfileLoader::Run()
107 {
109  return NS_OK;
110 }
111 
112 nsresult
114 {
115  const PRInt32 IOFLAGS_DEFAULT = -1;
116  const PRInt32 PERMISSIONS_DEFAULT = -1;
117  const PRInt32 FLAGS_DEFAULT = 0;
118 
119  nsresult rv;
120 
121  NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_UNEXPECTED);
122  NS_ENSURE_ARG_POINTER(mFile);
123 
124  nsCOMPtr<nsIDOMParser> domParser =
125  do_CreateInstance("@mozilla.org/xmlextras/domparser;1", &rv);
126  NS_ENSURE_SUCCESS(rv, rv);
127 
128  nsCOMPtr<nsIFileInputStream> fileStream =
129  do_CreateInstance("@mozilla.org/network/file-input-stream;1", &rv);
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  rv = fileStream->Init(mFile,
133  IOFLAGS_DEFAULT,
134  PERMISSIONS_DEFAULT,
135  FLAGS_DEFAULT);
136 
137  PRUint32 fileSize;
138  rv = fileStream->Available(&fileSize);
139  NS_ENSURE_SUCCESS(rv, rv);
140 
141  nsCOMPtr<nsIDOMDocument> doc;
142  rv = domParser->ParseFromStream(fileStream,
143  nsnull,
144  fileSize,
145  "text/xml",
146  getter_AddRefs(doc));
147  NS_ENSURE_SUCCESS(rv, rv);
148 
149  rv = fileStream->Close();
150  NS_ENSURE_SUCCESS(rv, rv);
151 
153  NS_ENSURE_SUCCESS(rv, rv);
154 
155  nsCOMPtr<nsIDOMElement> element;
156  rv = doc->GetDocumentElement(getter_AddRefs(element));
157  NS_ENSURE_SUCCESS(rv, rv);
158 
159  nsCOMPtr<nsIDOMNode> childNode;
160  rv = element->GetFirstChild(getter_AddRefs(childNode));
161  NS_ENSURE_SUCCESS(rv, rv);
162 
163  while (childNode) {
164  nsCOMPtr<nsIDOMElement> childElement = do_QueryInterface(childNode, &rv);
165 
166  if (NS_SUCCEEDED(rv)) {
167  nsString localName;
168  rv = childElement->GetLocalName(localName);
169  NS_ENSURE_SUCCESS(rv, rv);
170 
171  if (localName.EqualsLiteral("type")) {
172  PRUint32 type;
173  rv = GetType(childNode, &type);
174  NS_ENSURE_SUCCESS(rv, rv);
175  rv = mProfile->SetType(type);
176  NS_ENSURE_SUCCESS(rv, rv);
177  } else if (localName.EqualsLiteral("description")) {
178  nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(childNode);
179  if (dom3Node) {
180  nsString textContent;
181  rv = dom3Node->GetTextContent(textContent);
182  NS_ENSURE_SUCCESS(rv, rv);
183  rv = mProfile->SetDescription(textContent);
184  NS_ENSURE_SUCCESS(rv, rv);
185  }
186  } else if (localName.EqualsLiteral("priority")) {
187  nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(childNode);
188  if (dom3Node) {
189  nsString textContent;
190  rv = dom3Node->GetTextContent(textContent);
191  NS_ENSURE_SUCCESS(rv, rv);
192  PRInt32 priority = textContent.ToInteger(&rv);
193  NS_ENSURE_SUCCESS(rv, rv);
194 
195  PRBool hasQuality = PR_FALSE;
196  rv = childElement->HasAttribute(NS_LITERAL_STRING("quality"),
197  &hasQuality);
198  NS_ENSURE_SUCCESS(rv, rv);
199  if (hasQuality) {
200  nsString qualityString;
201  rv = childElement->GetAttribute(NS_LITERAL_STRING("quality"),
202  qualityString);
203  NS_ENSURE_SUCCESS(rv, rv);
204  NS_LossyConvertUTF16toASCII qualityCString(qualityString);
205  PRFloat64 quality = PR_strtod(qualityCString.get(), nsnull);
206  rv = mProfile->AddPriority((double)quality, priority);
207  NS_ENSURE_SUCCESS(rv, rv);
208  } else {
209  rv = mProfile->SetPriority(priority);
210  NS_ENSURE_SUCCESS(rv, rv);
211  }
212  }
213  } else if (localName.EqualsLiteral("id")) {
214  nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(childNode);
215  if (dom3Node) {
216  nsString textContent;
217  rv = dom3Node->GetTextContent(textContent);
218  NS_ENSURE_SUCCESS(rv, rv);
219  rv = mProfile->SetId(textContent);
220  NS_ENSURE_SUCCESS(rv, rv);
221  }
222  } else if (localName.EqualsLiteral("extension")) {
223  nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(childNode);
224  if (dom3Node) {
225  nsString textContent;
226  rv = dom3Node->GetTextContent(textContent);
227  NS_ENSURE_SUCCESS(rv, rv);
228  rv = mProfile->SetFileExtension(NS_ConvertUTF16toUTF8(textContent));
229  NS_ENSURE_SUCCESS(rv, rv);
230  }
231  } else if (localName.EqualsLiteral("container")) {
232  rv = ProcessContainer(mProfile, CONTAINER_GENERIC, childElement);
233  NS_ENSURE_SUCCESS(rv, rv);
234  } else if (localName.EqualsLiteral("audio")) {
235  rv = ProcessContainer(mProfile, CONTAINER_AUDIO, childElement);
236  NS_ENSURE_SUCCESS(rv, rv);
237  } else if (localName.EqualsLiteral("video")) {
238  rv = ProcessContainer(mProfile, CONTAINER_VIDEO, childElement);
239  NS_ENSURE_SUCCESS(rv, rv);
240  }
241  }
242 
243  rv = childNode->GetNextSibling(getter_AddRefs(childNode));
244  NS_ENSURE_SUCCESS(rv, rv);
245  }
246 
247  return NS_OK;
248 }
249 
250 nsresult
251 sbTranscodeProfileLoader::GetType(nsIDOMNode* aTypeNode, PRUint32* _retval)
252 {
253  NS_ENSURE_ARG_POINTER(aTypeNode);
254  NS_ENSURE_ARG_POINTER(_retval);
255 
256  nsresult rv;
257 
258  nsCOMPtr<nsIDOM3Node> dom3node = do_QueryInterface(aTypeNode, &rv);
259  NS_ENSURE_SUCCESS(rv, rv);
260 
261  nsString type;
262  rv = dom3node->GetTextContent(type);
263  NS_ENSURE_SUCCESS(rv, rv);
264 
265  if (type.EqualsLiteral("audio")) {
267  } else if (type.EqualsLiteral("video")) {
269  } else if (type.EqualsLiteral("image")) {
271  } else {
272  return NS_ERROR_INVALID_ARG;
273  }
274  return NS_OK;
275 }
276 
277 nsresult
278 sbTranscodeProfileLoader::ProcessAttribute(nsIDOMElement* aAttributeElement,
280 {
281  NS_ENSURE_ARG_POINTER(aAttributeElement);
282  NS_ENSURE_ARG_POINTER(_retval);
283 
284  nsresult rv;
285 
286  nsRefPtr<sbTranscodeProfileAttribute> attr =
288  NS_ENSURE_TRUE(attr, NS_ERROR_OUT_OF_MEMORY);
289 
290  nsString name;
291  rv = aAttributeElement->GetAttribute(NS_LITERAL_STRING("name"),
292  name);
293  NS_ENSURE_SUCCESS(rv, rv);
294  rv = attr->SetName(name);
295  NS_ENSURE_SUCCESS(rv, rv);
296 
297  nsString type;
298  rv = aAttributeElement->GetAttribute(NS_LITERAL_STRING("type"),
299  type);
300  NS_ENSURE_SUCCESS(rv, rv);
301 
302  nsString valueString;
303  rv = aAttributeElement->GetAttribute(NS_LITERAL_STRING("value"),
304  valueString);
305  NS_ENSURE_SUCCESS(rv, rv);
306 
307  if (type.EqualsLiteral("int")) {
308  PRInt32 value;
309 
310  value = valueString.ToInteger(&rv);
311  NS_ENSURE_SUCCESS(rv, rv);
312 
313  rv = attr->SetValue(sbNewVariant(value));
314  NS_ENSURE_SUCCESS(rv, rv);
315  }
316  else if (type.EqualsLiteral("string")) {
317  rv = attr->SetValue(sbNewVariant(valueString));
318  NS_ENSURE_SUCCESS(rv, rv);
319  }
320  else {
321  return NS_ERROR_NOT_IMPLEMENTED;
322  }
323 
324  rv = CallQueryInterface(attr.get(), _retval);
325  NS_ENSURE_SUCCESS(rv, rv);
326 
327  return NS_OK;
328 }
329 
330 nsresult
331 sbTranscodeProfileLoader::ProcessProperty(nsIDOMElement* aPropertyElement,
332  sbITranscodeProfileProperty** _retval)
333 {
334  NS_ENSURE_ARG_POINTER(aPropertyElement);
335  NS_ENSURE_ARG_POINTER(_retval);
336 
337  nsresult rv;
338 
339  nsRefPtr<sbTranscodeProfileProperty> property =
341  NS_ENSURE_TRUE(property, NS_ERROR_OUT_OF_MEMORY);
342 
343  nsString attributeValue;
344  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("name"),
345  attributeValue);
346  NS_ENSURE_SUCCESS(rv, rv);
347  rv = property->SetPropertyName(attributeValue);
348  NS_ENSURE_SUCCESS(rv, rv);
349 
350  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("hidden"),
351  attributeValue);
352  NS_ENSURE_SUCCESS(rv, rv);
353  if (attributeValue.IsEmpty() ||
354  attributeValue.EqualsLiteral("0") ||
355  attributeValue.LowerCaseEqualsLiteral("false"))
356  {
357  rv = property->SetHidden(PR_FALSE);
358  NS_ENSURE_SUCCESS(rv, rv);
359  }
360  else {
361  rv = property->SetHidden(PR_TRUE);
362  NS_ENSURE_SUCCESS(rv, rv);
363  }
364 
365  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("mapping"),
366  attributeValue);
367  NS_ENSURE_SUCCESS(rv, rv);
368  if (!attributeValue.IsEmpty()) {
369  rv = property->SetMapping(NS_ConvertUTF16toUTF8(attributeValue));
370  NS_ENSURE_SUCCESS(rv, rv);
371  }
372 
373  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("scale"),
374  attributeValue);
375  NS_ENSURE_SUCCESS(rv, rv);
376  if (!attributeValue.IsEmpty()) {
377  rv = property->SetScale(NS_ConvertUTF16toUTF8(attributeValue));
378  NS_ENSURE_SUCCESS(rv, rv);
379  }
380 
381  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("type"),
382  attributeValue);
383  NS_ENSURE_SUCCESS(rv, rv);
384 
385  if (attributeValue.EqualsLiteral("int")) {
386  PRInt32 value;
387 
388  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("min"),
389  attributeValue);
390  NS_ENSURE_SUCCESS(rv, rv);
391 
392  value = attributeValue.ToInteger(&rv);
393  NS_ENSURE_SUCCESS(rv, rv);
394 
395  rv = property->SetValueMin(sbNewVariant(value));
396  NS_ENSURE_SUCCESS(rv, rv);
397 
398  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("max"),
399  attributeValue);
400  NS_ENSURE_SUCCESS(rv, rv);
401 
402  value = attributeValue.ToInteger(&rv);
403  NS_ENSURE_SUCCESS(rv, rv);
404 
405  rv = property->SetValueMax(sbNewVariant(value));
406  NS_ENSURE_SUCCESS(rv, rv);
407 
408  rv = aPropertyElement->GetAttribute(NS_LITERAL_STRING("default"),
409  attributeValue);
410  NS_ENSURE_SUCCESS(rv, rv);
411 
412  value = attributeValue.ToInteger(&rv);
413  NS_ENSURE_SUCCESS(rv, rv);
414 
415  rv = property->SetValue(sbNewVariant(value));
416  NS_ENSURE_SUCCESS(rv, rv);
417  } else {
418  return NS_ERROR_NOT_IMPLEMENTED;
419  }
420 
421  rv = CallQueryInterface(property.get(), _retval);
422  NS_ENSURE_SUCCESS(rv, rv);
423 
424  return NS_OK;
425 }
426 
427 nsresult
429  ContainerType_t aContainerType,
430  nsIDOMElement* aContainer)
431 {
432  NS_ENSURE_ARG_POINTER(aProfile);
433  NS_ENSURE_ARG_POINTER(aContainer);
434 
435  nsresult rv;
436 
437  nsCOMPtr<nsIMutableArray> properties =
438  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
439  NS_ENSURE_SUCCESS(rv, rv);
440 
441  nsCOMPtr<nsIMutableArray> attributes =
442  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
443  NS_ENSURE_SUCCESS(rv, rv);
444 
445  nsCOMPtr<nsIDOMNode> childNode;
446  rv = aContainer->GetFirstChild(getter_AddRefs(childNode));
447  NS_ENSURE_SUCCESS(rv, rv);
448 
449  while (childNode) {
450  nsCOMPtr<nsIDOMElement> childElement = do_QueryInterface(childNode);
451  if (childElement) {
452  nsString localName;
453  rv = childElement->GetLocalName(localName);
454  NS_ENSURE_SUCCESS(rv, rv);
455 
456  if (localName.EqualsLiteral("type")) {
457  nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(childNode, &rv);
458  NS_ENSURE_SUCCESS(rv, rv);
459 
460  nsString textContent;
461  rv = dom3Node->GetTextContent(textContent);
462  NS_ENSURE_SUCCESS(rv, rv);
463 
464  switch (aContainerType) {
465  case CONTAINER_GENERIC:
466  rv = aProfile->SetContainerFormat(textContent);
467  break;
468  case CONTAINER_AUDIO:
469  rv = aProfile->SetAudioCodec(textContent);
470  break;
471  case CONTAINER_VIDEO:
472  rv = aProfile->SetVideoCodec(textContent);
473  break;
474  default:
475  rv = NS_ERROR_UNEXPECTED;
476  }
477  NS_ENSURE_SUCCESS(rv, rv);
478  }
479  else if (localName.EqualsLiteral("attribute")) {
480  nsCOMPtr<sbITranscodeProfileAttribute> attr;
481  rv = ProcessAttribute(childElement, getter_AddRefs(attr));
482  NS_ENSURE_SUCCESS(rv, rv);
483 
484  rv = attributes->AppendElement(attr, PR_FALSE);
485  NS_ENSURE_SUCCESS(rv, rv);
486  }
487  else if (localName.EqualsLiteral("property")) {
488  nsCOMPtr<sbITranscodeProfileProperty> property;
489  rv = ProcessProperty(childElement, getter_AddRefs(property));
490  NS_ENSURE_SUCCESS(rv, rv);
491 
492  rv = properties->AppendElement(property, PR_FALSE);
493  NS_ENSURE_SUCCESS(rv, rv);
494  }
495  else if (localName.EqualsLiteral("quality-property")) {
496  nsString attrVal;
497  rv = childElement->GetAttribute(NS_LITERAL_STRING("quality"), attrVal);
498  NS_ENSURE_SUCCESS(rv, rv);
499  nsCString attrCVal = NS_LossyConvertUTF16toASCII(attrVal);
500  PRFloat64 quality = PR_strtod(attrCVal.get(), nsnull);
501 
502  rv = childElement->GetAttribute(NS_LITERAL_STRING("value"), attrVal);
503  NS_ENSURE_SUCCESS(rv, rv);
504  attrCVal = NS_LossyConvertUTF16toASCII(attrVal);
505  PRFloat64 value = PR_strtod(attrCVal.get(), nsnull);
506 
507  rv = childElement->GetAttribute(NS_LITERAL_STRING("name"), attrVal);
508  NS_ENSURE_SUCCESS(rv, rv);
509 
510  if (attrVal.EqualsLiteral("bitrate")) {
511  NS_ENSURE_STATE(aContainerType == CONTAINER_AUDIO);
512  rv = aProfile->AddAudioBitrate((double)quality, (double)value);
513  NS_ENSURE_SUCCESS(rv, rv);
514  }
515  else if (attrVal.EqualsLiteral("bpp")) {
516  NS_ENSURE_STATE(aContainerType == CONTAINER_VIDEO);
517  rv = aProfile->AddVideoBPP((double)quality, (double)value);
518  NS_ENSURE_SUCCESS(rv, rv);
519  }
520  else {
521  NS_ENSURE_TRUE(false, NS_ERROR_UNEXPECTED);
522  }
523  }
524  }
525  rv = childNode->GetNextSibling(getter_AddRefs(childNode));
526  NS_ENSURE_SUCCESS(rv, rv);
527  }
528 
529  switch (aContainerType) {
530  case CONTAINER_GENERIC:
531  rv = aProfile->SetContainerProperties(properties);
532  rv = aProfile->SetContainerAttributes(attributes);
533  break;
534  case CONTAINER_AUDIO:
535  rv = aProfile->SetAudioProperties(properties);
536  rv = aProfile->SetAudioAttributes(attributes);
537  break;
538  case CONTAINER_VIDEO:
539  rv = aProfile->SetVideoProperties(properties);
540  rv = aProfile->SetVideoAttributes(attributes);
541  break;
542  default:
543  rv = NS_ERROR_UNEXPECTED;
544  }
545  NS_ENSURE_SUCCESS(rv, rv);
546 
547  return NS_OK;
548 }
nsRefPtr< sbTranscodeProfile > mProfile
const unsigned long TRANSCODE_TYPE_IMAGE
return NS_OK
tabData attributes[name]
nsresult GetType(nsIDOMNode *aTypeNode, PRUint32 *_retval)
nsresult ProcessProperty(nsIDOMElement *aPropertyElement, sbITranscodeProfileProperty **_retval)
function doc() browser.contentDocument
An object that can create an sbITranscodeProfile from an XML description file.
const unsigned long TRANSCODE_TYPE_AUDIO
An object defining a transcoding profile.
Songbird Variant Utility Definitions.
const unsigned long TRANSCODE_TYPE_AUDIO_VIDEO
NS_DECL_ISUPPORTS NS_DECL_SBITRANSCODEPROFILELOADER NS_DECL_NSIRUNNABLE sbTranscodeProfileLoader()
nsresult AddVideoBPP(double aQuality, double aBPP)
nsresult AddAudioBitrate(double aQuality, double aBitrate)
NS_IMPL_THREADSAFE_ISUPPORTS2(sbTranscodeProfileLoader, sbITranscodeProfileLoader, nsIRunnable)
const FLAGS_DEFAULT
nsresult ProcessAttribute(nsIDOMElement *aAttributeElement, sbITranscodeProfileAttribute **_retval)
countRef value
Definition: FeedWriter.js:1423
nsresult ProcessContainer(sbTranscodeProfile *aProfile, ContainerType_t aContainerType, nsIDOMElement *aContainer)