home *** CD-ROM | disk | FTP | other *** search
/ Freelog 112 / FreelogNo112-NovembreDecembre2012.iso / Multimedia / Songbird / Songbird_2.0.0-2311_windows-i686-msvc8.exe / components / sbPlaylistReaderManager.js < prev    next >
Text File  |  2012-06-08  |  11KB  |  374 lines

  1. /*
  2.  *=BEGIN SONGBIRD GPL
  3.  *
  4.  * This file is part of the Songbird web player.
  5.  *
  6.  * Copyright(c) 2005-2010 POTI, Inc.
  7.  * http://www.songbirdnest.com
  8.  *
  9.  * This file may be licensed under the terms of of the
  10.  * GNU General Public License Version 2 (the ``GPL'').
  11.  *
  12.  * Software distributed under the License is distributed
  13.  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
  14.  * express or implied. See the GPL for the specific language
  15.  * governing rights and limitations.
  16.  *
  17.  * You should have received a copy of the GPL along with this
  18.  * program. If not, go to http://www.gnu.org/licenses/gpl.html
  19.  * or write to the Free Software Foundation, Inc.,
  20.  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21.  *
  22.  *=END SONGBIRD GPL
  23.  */
  24.  
  25. //
  26. // sbIPlaylistReaderManager Object
  27. //
  28. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  29.  
  30. const Cc = Components.classes;
  31. const Ci = Components.interfaces;
  32. const Cr = Components.results;
  33.  
  34. function CPlaylistReaderManager()
  35. {
  36.   var catMan = Cc["@mozilla.org/categorymanager;1"]
  37.                  .getService(Ci.nsICategoryManager);
  38.  
  39.   var readers = catMan.enumerateCategory("playlist-reader");
  40.   while (readers.hasMoreElements()) {
  41.     var entry = readers.getNext();
  42.     entry = entry.QueryInterface(Ci.nsISupportsCString);
  43.     var contractid = catMan.getCategoryEntry("playlist-reader", entry);
  44.  
  45.     try {
  46.       var aReader = Cc[contractid].createInstance(Ci.sbIPlaylistReader);
  47.       this.m_Readers.push(aReader);
  48.     }
  49.     catch(e) {
  50.     }
  51.   }
  52.  
  53.   // Cache the supported strings
  54.   for(var i in this.m_Readers)
  55.   {
  56.     var nExtensionsCount = {};
  57.     var aExts = this.m_Readers[i].supportedFileExtensions(nExtensionsCount);
  58.     this.m_Extensions = this.m_Extensions.concat(aExts);
  59.     var nMIMETypesCount = {};
  60.     var aMIMETypes = this.m_Readers[i].supportedMIMETypes(nMIMETypesCount);
  61.     this.m_MIMETypes = this.m_MIMETypes.concat(aMIMETypes);
  62.   }
  63.  
  64.   var obs = Cc["@mozilla.org/observer-service;1"]
  65.               .getService(Ci.nsIObserverService);
  66.   obs.addObserver(this, "quit-application", false);
  67. }
  68.  
  69. CPlaylistReaderManager.prototype.constructor = CPlaylistReaderManager;
  70.  
  71. CPlaylistReaderManager.prototype =
  72. {
  73.   classDescription: "Songbird Playlist Reader Manager Interface",
  74.   classID:          Components.ID("{ced5902c-bd90-4099-acee-77487a5b1d13}"),
  75.   contractID:       "@songbirdnest.com/Songbird/PlaylistReaderManager;1",
  76.  
  77.   originalURI: null,
  78.  
  79.   m_rootContractID: "@songbirdnest.com/Songbird/Playlist/Reader/",
  80.   m_interfaceID: Components.interfaces.sbIPlaylistReader,
  81.   m_Readers: new Array(),
  82.   m_Extensions: new Array(),
  83.   m_MIMETypes: new Array(),
  84.  
  85.   getTempFilename: function(aExtension)
  86.   {
  87.     var extension;
  88.     if (aExtension)
  89.       extension = aExtension;
  90.     else
  91.       extension = "tmp";
  92.     var file = Components.classes["@mozilla.org/file/directory_service;1"]
  93.                          .getService(Components.interfaces.nsIProperties)
  94.                          .get("TmpD", Components.interfaces.nsIFile);
  95.     file.append("songbird." + extension);
  96.     file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664);
  97.  
  98.     return file.path;
  99.   },
  100.  
  101.   getFileExtension: function(aThing)
  102.   {
  103.     var name = "";
  104.     if (aThing instanceof Ci.nsIURL) {
  105.       if ("" != aThing.fileExtension) {
  106.         return aThing.fileExtension;
  107.       }
  108.     }
  109.     if (aThing instanceof Ci.nsIURI) {
  110.       name = aThing.path;
  111.     }
  112.     if (aThing instanceof Ci.nsIFile) {
  113.       name = aThing.leafName;
  114.     }
  115.     // find the file extension
  116.     var m = /\.([^\.\/]+)$/(name);
  117.     if (m) {
  118.       return m[1];
  119.     } else {
  120.       return null;
  121.     } 
  122.   },
  123.  
  124.   //sbIPlaylistReaderManager
  125.   loadPlaylist: function(aURI, aMediaList, aContentType, aAddDistinctOnly, aPlaylistReaderListener)
  126.   {
  127.     const PlaylistReaderListener = new Components.Constructor("@songbirdnest.com/Songbird/PlaylistReaderListener;1", "sbIPlaylistReaderListener");
  128.  
  129.     var theExtension = this.getFileExtension(aURI);
  130.  
  131.     if (aURI instanceof Ci.nsIFileURL)
  132.     {
  133.       var file = aURI.QueryInterface(Ci.nsIFileURL).file;
  134.  
  135.       // Can't be a playlist if there is nothing in it
  136.       if (!file.exists() || file.fileSize == 0) {
  137.         return -1;
  138.       }
  139.  
  140.       // If we are trying to load highly generic
  141.       // content types, try to guess better ones
  142.       if (aContentType == null ||
  143.           aContentType == "" ||
  144.           aContentType == "text/html" ||
  145.           aContentType == "text/xml" ||
  146.           aContentType == "text/plain" ||
  147.           aContentType == "application/xhtml" ||
  148.           aContentType == "application/xhtml+xml" ||
  149.           aContentType == "application/xml") {
  150.         aContentType = this.guessMimeType(file);
  151.         if (!aContentType) {
  152.           return -1;
  153.         }
  154.       }
  155.  
  156.       if (!this.originalURI) {
  157.         this.originalURI = aURI;
  158.       }
  159.  
  160.       try {
  161.         this.read(file, aMediaList, aContentType, aAddDistinctOnly);
  162.         if (aPlaylistReaderListener && aPlaylistReaderListener.observer) {
  163.           aPlaylistReaderListener.observer.observe(aMediaList, "success", "");
  164.         }
  165.         return 1;
  166.       }
  167.       catch(e) {
  168.         if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
  169.           return -1
  170.         }
  171.         throw e;
  172.       }
  173.       finally {
  174.         this.originalURI = null;
  175.       }
  176.  
  177.     }
  178.     else
  179.     {
  180.       // Remember the original url.
  181.       this.originalURI = aURI;
  182.  
  183.       var browser = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
  184.                       .createInstance(Ci.nsIWebBrowserPersist);
  185.  
  186.       if(!browser) return -1;
  187.  
  188.       // Create a local file to save the remote playlist to
  189.       var destFile = this.getTempFilename(theExtension);
  190.       var localFile = Cc["@mozilla.org/file/local;1"]
  191.                         .createInstance(Ci.nsILocalFile);
  192.       localFile.initWithPath(destFile);
  193.  
  194.       var ios = Cc["@mozilla.org/network/io-service;1"]
  195.                 .getService(Ci.nsIIOService);
  196.       var localFileUri = ios.newFileURI(localFile);
  197.  
  198.       var registerFileForDelete = Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
  199.                                     .getService(Ci.nsPIExternalAppLauncher);
  200.       registerFileForDelete.deleteTemporaryFileOnExit(localFile);
  201.  
  202.       var prListener = null;
  203.       if(aPlaylistReaderListener)
  204.       {
  205.         prListener = aPlaylistReaderListener;
  206.       }
  207.       else
  208.       {
  209.         prListener = (new PlaylistReaderListener()).QueryInterface(Ci.sbIPlaylistReaderListener);
  210.       }
  211.  
  212.       prListener.originalURI = this.originalURI;
  213.       prListener.mediaList = aMediaList;
  214.       prListener.destinationURI = localFileUri;
  215.       prListener.addDistinctOnly = aAddDistinctOnly;
  216.  
  217.       // let the download decompress gzip as appropriate
  218.       browser.persistFlags &=
  219.         ~(Ci.nsIWebBrowserPersist.PERSIST_FLAGS_NO_CONVERSION);
  220.  
  221.       browser.progressListener = prListener;
  222.  
  223.       browser.saveURI(aURI, null, null, null, "", localFileUri);
  224.  
  225.       return 1;
  226.     }
  227.  
  228.     return 1;
  229.   },
  230.  
  231.   read: function(aFile, aMediaList, aContentType, aAddDistinctOnly, aPlaylistFormatType)
  232.   {
  233.     if (!this.originalURI) {
  234.       var ioService = Cc["@mozilla.org/network/io-service;1"]
  235.                         .getService(Ci.nsIIOService);
  236.       this.originalURI = ioService.newFileURI(aFile);
  237.     }
  238.  
  239.     var theExtension = this.getFileExtension(aFile);
  240.     for (var r in this.m_Readers)
  241.     {
  242.       var aReader = this.m_Readers[r];
  243.       if(!aContentType)
  244.       {
  245.         var nExtensionsCount = {};
  246.         var theExtensions = aReader.supportedFileExtensions(nExtensionsCount);
  247.  
  248.         if (SB_ArrayContains(theExtensions, theExtension)) {
  249.  
  250.           // Handoff the original url
  251.           aReader.originalURI = this.originalURI;
  252.           this.originalURI = null;
  253.  
  254.           aReader.read(aFile, aMediaList, aAddDistinctOnly, aPlaylistFormatType);
  255.           return;
  256.         }
  257.       }
  258.       else
  259.       {
  260.         var nMIMTypeCount = {};
  261.         var theMIMETypes = aReader.supportedMIMETypes(nMIMTypeCount);
  262.  
  263.         if (SB_ArrayContains(theMIMETypes, aContentType)) {
  264.  
  265.           // Handoff the original url
  266.           aReader.originalURI = this.originalURI;
  267.           this.originalURI = null;
  268.  
  269.           aReader.read(aFile, aMediaList, aAddDistinctOnly, aPlaylistFormatType);
  270.           return;
  271.         }
  272.       }
  273.     }
  274.  
  275.     // Couldn't handle it so throw
  276.     throw Cr.NS_ERROR_NOT_AVAILABLE;
  277.   },
  278.  
  279.   supportedFileExtensions: function(nExtCount)
  280.   {
  281.     nExtCount.value = this.m_Extensions.length;
  282.     return this.m_Extensions;
  283.   },
  284.  
  285.   supportedMIMETypes: function(nMIMECount)
  286.   {
  287.     nMIMECount.value = this.m_MIMETypes.length;
  288.     return this.m_MIMETypes;
  289.   },
  290.  
  291.   guessMimeType: function(file)
  292.   {
  293.     // Read a few bytes from the file
  294.     var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
  295.                             .createInstance(Components.interfaces.nsIFileInputStream);
  296.     var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
  297.                             .createInstance(Components.interfaces.nsIScriptableInputStream);
  298.     fstream.init(file, -1, 0, 0);
  299.     sstream.init(fstream);
  300.     var str = sstream.read(4096);
  301.     sstream.close();
  302.     fstream.close();
  303.  
  304.     // This object literal maps mime types to regexps.  If the content matches
  305.     // the given regexp, it is assigned the given mime type.
  306.     var regexps = [
  307.       {
  308.         // Note: "\s\S" matches *everything*, unlike "." which matches
  309.         // everything except system-specific variations on \n.
  310.         regexp:    /<\?xml[\s\S]*<rss/,
  311.         mimeType: "application/rss+xml"
  312.       },
  313.       {
  314.         regexp:    /<\?xml[\s\S]*xmlns="http:\/\/www\.w3\.org\/2005\/Atom"/,
  315.         mimeType: "application/atom+xml"
  316.       },
  317.       {
  318.         regexp:    /^\[playlist\]/i,
  319.         mimeType: "audio/x-scpls"
  320.       },
  321.       {
  322.         regexp:    /^#EXTM3U/i,
  323.         mimeType: "audio/mpegurl"
  324.       },
  325.       {
  326.         regexp:    /<html/i,
  327.         mimeType: "text/html"
  328.       },
  329.       {
  330.         regexp:    /^(http|mms|rtsp)/im,
  331.         mimeType: "audio/mpegurl"
  332.       },
  333.       {
  334.         regexp:    /.*(mp3|ogg|flac|wav|m4a|wma|wmv|asx|asf|avi|mov|mpg|mp4)$/im,
  335.         mimeType: "audio/mpegurl"
  336.       },
  337.       {
  338.         regexp:    /^<ASX/i,
  339.         mimeType: "video/x-ms-asf"
  340.       }
  341.     ];
  342.  
  343.     for(var i = 0; i < regexps.length; i++) {
  344.       var re = regexps[i].regexp;
  345.       if(re.test(str)) {
  346.         return regexps[i].mimeType;
  347.       }
  348.     }
  349.  
  350.     // Otherwise, we have no guess
  351.     return null;
  352.   },
  353.  
  354.   observe: function(aSubject, aTopic, aData) {
  355.     var obs = Cc["@mozilla.org/observer-service;1"]
  356.                 .getService(Ci.nsIObserverService);
  357.     obs.removeObserver(this, "quit-application");
  358.  
  359.     for (let i in this.m_Readers) {
  360.       this.m_Readers[i] = null;
  361.     }
  362.   },
  363.  
  364.   QueryInterface: XPCOMUtils.generateQI([Ci.sbIPlaylistReaderManager])
  365. };
  366.  
  367. function SB_ArrayContains(a, v) {
  368.   return a.some(function(e) { return e == v; } );
  369. }
  370.  
  371. function NSGetModule(compMgr, fileSpec) {
  372.   return XPCOMUtils.generateModule([CPlaylistReaderManager]);
  373. }
  374.