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

  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.  
  27. const Cc = Components.classes;
  28. const Ci = Components.interfaces;
  29. const Cu = Components.utils;
  30.  
  31. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  32. Cu.import("resource://app/jsmodules/sbProperties.jsm");
  33. Cu.import("resource://app/jsmodules/SBJobUtils.jsm");
  34. Cu.import("resource://app/jsmodules/ArrayConverter.jsm");
  35.  
  36. //------------------------------------------------------------------------------
  37.  
  38. //
  39. // @brief A XPCOM service to help with importing URI's into a specified media
  40. //        list. For more information, see sbIURIImportService.idl.
  41. //
  42. function sbURIImportService()
  43. {
  44. }
  45.  
  46. sbURIImportService.prototype = 
  47. {
  48.   _importInProgress: false,  // are we currently importing a drop ?
  49.   _uriArray:        null,    // array of URI's to import
  50.   _directoryList:    [],     // queue of nsIFile directories to scan
  51.   _targetList:       null,   // target mediaList for the drop
  52.   _targetPosition:   -1,     // position in the mediaList we should drop at
  53.   _firstMediaItem:   null,   // first mediaItem that was handled in this drop
  54.   _scanList:         null,   // list of newly created medaItems for metadata scan
  55.   _window:           null,   // window that received this drop
  56.   _listener:         null,   // listener object, for notifications
  57.   _totalImported:    0,      // number of items imported in the library
  58.   _totalInserted:    0,      // number of items inserted in the medialist
  59.   _totalDups:        0,      // number of items we already had in the library
  60.   _otherDrops:       0,      // number of other drops handled (eg, XPI, JAR)
  61.   _mainLibrary:      null,   // The main library
  62.  
  63.  
  64.   // sbIURIImportService
  65.   importURIArray: function(aMutableURIArray, 
  66.                            aDOMWindow, 
  67.                            aTargetMediaList, 
  68.                            aTargetPosition,
  69.                            aImportListener) 
  70.   {
  71.     this._window = aDOMWindow;
  72.     this._targetList = aTargetMediaList;
  73.     this._targetPosition = aTargetPosition;
  74.     this._listener = aImportListener;
  75.  
  76.     // the array to record items to feed to the metadata scanner
  77.     if (!this._scanList) {
  78.       this._scanList = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
  79.                          .createInstance(Ci.nsIMutableArray);
  80.     }
  81.  
  82.     // Reset stats and various job variables
  83.     this._firstMediaItem = null;
  84.     this._totalImported = 0;
  85.     this._totalInserted = 0;
  86.     this._totalDups = 0;
  87.     this._mainLibrary = Cc["@songbirdnest.com/Songbird/library/Manager;1"]
  88.                           .getService(Ci.sbILibraryManager)
  89.                           .mainLibrary;
  90.  
  91.     this._uriArray = aMutableURIArray;
  92.  
  93.     // If we are already importing, our entries will be processed at the end
  94.     // of the current batch. Otherwise, we need to start a new one.
  95.     if (!this._importInProgress) {
  96.       // Remember that we are currently processing a batch - if more files are
  97.       // dropped while we're importing, they will be added to the end of the
  98.       // batch import.
  99.       this._importInProgress = true;
  100.  
  101.       // Begin processing the URI array.
  102.       // (The first item will be handled immediately, and the subsequent ones
  103.       // will be processed each time a new "frame" occurs, on a timer).
  104.       this._importDropFrame();
  105.     }
  106.   },
  107.  
  108.   // give a little bit of time for the main thread to react to UI events, and 
  109.   // then execute the next frame of the drop import session.
  110.   _nextImportDropFrame: function() 
  111.   {
  112.     this._timer = Cc["@mozilla.org/timer;1"]
  113.                     .createInstance(Ci.nsITimer);
  114.     this._timer.initWithCallback(this, 10, Ci.nsITimer.TYPE_ONE_SHOT);    
  115.   },
  116.  
  117.   // nsITimer
  118.   notify: function(timer) 
  119.   {
  120.     this._timer = null;
  121.     this._importDropFrame();
  122.   },
  123.  
  124.   // Executes one frame of the drop import session
  125.   _importDropFrame: function() 
  126.   {
  127.     try {
  128.       // any more files to process ?
  129.       if (this._uriArray.length > 0) {
  130.         
  131.         // get the first of the remaining files
  132.         var uri = this._uriArray.queryElementAt(0, Ci.nsIURI);
  133.         
  134.         // remove it from the array of files to process
  135.         this._uriArray.removeElementAt(0);
  136.  
  137.         if (uri) {
  138.           // make a file URL object and check if the object is a directory.
  139.           // if it is a directory, then we record it in a separate array,
  140.           // which we will process at the end of the batch.
  141.           var fileUrl;
  142.           try {
  143.             fileUrl = uri.QueryInterface(Ci.nsIFileURL);
  144.           } 
  145.           catch (e) { 
  146.             fileUrl = null; 
  147.           }
  148.           if (fileUrl) {
  149.             // is this is a directory?
  150.             if (fileUrl.file.isDirectory()) {
  151.               // yes, record it and delay processing
  152.               this._directoryList.push(fileUrl.file);
  153.               // continue with the current batch
  154.               this._nextImportDropFrame();
  155.               return;
  156.             }
  157.           }
  158.  
  159.           // process this item
  160.           this._importDropFile(uri);
  161.         }
  162.  
  163.         // continue with the current batch
  164.         this._nextImportDropFrame();
  165.       } 
  166.       else {
  167.         // there are no more items in the drop array, start the metadata scanner
  168.         // if we created any mediaitem
  169.         if (this._scanList && this._scanList.length > 0) {
  170.           var metadataService = 
  171.             Cc["@songbirdnest.com/Songbird/FileMetadataService;1"]
  172.               .getService(Ci.sbIFileMetadataService);
  173.  
  174.           metadataService.read(this._scanList);
  175.           this._scanList = null;
  176.         }
  177.         
  178.         // see if there are any directories to be scanned now.
  179.         if (this._directoryList.length > 0) {
  180.  
  181.           // yes, there are, import them.
  182.           this._importDropDirectories();
  183.           
  184.           // continue with the current batch, in case more stuff
  185.           // has been dropped. this shouldnt be possible because the
  186.           // mediascan dialog is modal, but it is better to check than
  187.           // to lose drops
  188.           this._nextImportDropFrame();
  189.         } 
  190.         else {
  191.           // all done.
  192.           this._dropComplete();
  193.         }
  194.       }
  195.     } 
  196.     catch (e) {
  197.       // oops, something wrong happened, we do not want to abort the whole
  198.       // import batch tho, so just print a debug message and try the next
  199.       // frame
  200.       Components.utils.reportError(e);
  201.       this._nextImportDropFrame();
  202.     }
  203.   },
  204.  
  205.   // import the given file URI into the target library and optionally inserts in
  206.   // into the target playlist at the desired spot. if the item already exists,
  207.   // it is only inserted to the playlist
  208.   _importDropFile: function(aURI) {
  209.     try {    
  210.       // is this a media url ?
  211.       let typeSniffer = 
  212.         Cc["@songbirdnest.com/Songbird/Mediacore/TypeSniffer;1"]
  213.           .createInstance(Ci.sbIMediacoreTypeSniffer);
  214.       let Application = Cc["@mozilla.org/fuel/application;1"]
  215.                           .getService(Ci.fuelIApplication);
  216.  
  217.       let isValidMediaURL = typeSniffer.isValidMediaURL(aURI);
  218.       if (!Application.prefs.getValue("songbird.mediascan.enableVideoImporting", true)
  219.           && typeSniffer.isValidVideoURL(aURI)) {
  220.         isValidMediaURL = false;
  221.       }
  222.  
  223.       if (isValidMediaURL) {
  224.         // check whether the item already exists in the library 
  225.         // for the target list
  226.         let item = 
  227.           this._getFirstItemByProperty(this._targetList.library,
  228.                                        SBProperties.contentURL,
  229.                                        aURI.spec);
  230.         // If we didn't find the content URL try the originURL
  231.         if (!item) {
  232.           item = 
  233.             this._getFirstItemByProperty(this._targetList.library,
  234.                                          SBProperties.originURL,
  235.                                          aURI.spec);
  236.         }
  237.         let mainLibraryItem = false;
  238.         // If we're not dropping on the main library look to see if the main
  239.         // library knows about this item. If it does, then use that item to add
  240.         if (!this._targetList.library.equals(this._mainLibrary)) {
  241.           if (!item) {
  242.             item = this._getFirstItemByProperty(this._mainLibrary,
  243.                                                 SBProperties.contentURL,
  244.                                                 aURI.spec);
  245.           }
  246.           // If we didn't find the content URL try the originURL
  247.           if (!item) {
  248.             item = 
  249.               this._getFirstItemByProperty(this._mainLibrary,
  250.                                            SBProperties.originURL,
  251.                                            aURI.spec);
  252.           }
  253.           mainLibraryItem = item != null;
  254.         }
  255.         // if the item didnt exist before, create it now
  256.         let itemAdded = false;
  257.         if (mainLibraryItem || !item) {
  258.           let holder = {};
  259.           if (!mainLibraryItem) {
  260.               
  261.               itemAdded = 
  262.                 this._targetList.library.createMediaItemIfNotExist(aURI, 
  263.                                                                    null, 
  264.                                                                    holder);
  265.               item = holder.value;
  266.           }
  267.           else {
  268.             
  269.             // If we add it from the main library, we need to get the item
  270.             // that might have been created and use that
  271.             let newItem = this._targetList.library.addItem(item);
  272.             itemAdded = newItem && !newItem.equals(item);
  273.             if (newItem) {
  274.               item = newItem;
  275.             }
  276.           }
  277.           if (itemAdded) {
  278.             this._scanList.appendElement(item, false);
  279.             this._totalImported++;
  280.           }
  281.         } 
  282.  
  283.         // The item was not added because it was a duplicate.
  284.         if (!itemAdded) {
  285.           this._totalDups++;
  286.         }
  287.  
  288.         // if the item is valid, and we are inserting in a medialist, insert it 
  289.         // to the requested position
  290.         if (item) {
  291.           if ((this._targetList instanceof Ci.sbIOrderableMediaList) &&
  292.               (this._targetPosition >= 0) && 
  293.               (this._targetPosition < this._targetList.length)) 
  294.           {
  295.             this._targetList.insertBefore(this._targetPosition, item);
  296.             this._targetPosition++;
  297.           } 
  298.           else {
  299.             this._targetList.add(item);
  300.           }
  301.           this._totalInserted++;
  302.         }
  303.         // report the first item that was dropped
  304.         if (!this._firstMediaItem) {
  305.           this._firstMediaItem = item;
  306.           if (this._listener) {
  307.             this._listener.onFirstMediaItem(this._targetList, item);
  308.           }
  309.         }
  310.       } 
  311.     } 
  312.     catch (e) {
  313.       Components.utils.reportError(e);
  314.     }
  315.   },
  316.  
  317.   // search for an item inside a list based on a property value. this is used
  318.   // by the drop handler to determine if a drop item is already in the target 
  319.   // library, by looking for its contentURL.
  320.   _getFirstItemByProperty: function(aMediaList, aProperty, aValue) 
  321.   {
  322.     var listener = {
  323.       item: null,
  324.       onEnumerationBegin: function() {
  325.       },
  326.       onEnumeratedItem: function(list, item) {
  327.         this.item = item;
  328.         return Components.interfaces.sbIMediaListEnumerationListener.CANCEL;
  329.       },
  330.       onEnumerationEnd: function() {
  331.       }
  332.     };
  333.  
  334.     aMediaList.enumerateItemsByProperty(aProperty,
  335.                                         aValue,
  336.                                         listener);
  337.     return listener.item;
  338.   },
  339.  
  340.   // trigger the import of all directory entries that have been defered until
  341.   // this point. this launches the media scanner dialog box.
  342.   _importDropDirectories: function() 
  343.   {
  344.     var importService = 
  345.       Cc['@songbirdnest.com/Songbird/DirectoryImportService;1']
  346.         .getService(Ci.sbIDirectoryImportService);
  347.     
  348.     var job = importService.import(ArrayConverter.nsIArray(this._directoryList),
  349.                                    this._targetList, this._targetPosition);
  350.     
  351.     // Reset list of directories
  352.     this._directoryList = [];
  353.                                    
  354.     SBJobUtils.showProgressDialog(job, this._window, /** No delay **/ 0);
  355.     
  356.     // If this job provided the first item, we may want to play it
  357.     if (!this._firstMediaItem) {
  358.       var allItems = job.enumerateAllItems();
  359.       if (allItems.hasMoreElements()) {
  360.         this._firstMediaItem = 
  361.           allItems.getNext().QueryInterface(Ci.sbIMediaItem);
  362.         
  363.         if (this._listener) {
  364.           this._listener.
  365.             onFirstMediaItem(this._targetList, this._firstMediaItem);
  366.         }
  367.       }
  368.     }
  369.  
  370.     this._totalImported += job.totalAddedToLibrary;
  371.     this._totalInserted += job.totalAddedToMediaList;
  372.     this._totalDups += job.totalDuplicates;
  373.   },
  374.   
  375.   // called when the whole drop handling operation has completed, used
  376.   // to notify the original caller and free up any resources we can
  377.   _dropComplete: function() 
  378.   {
  379.     if (this._listener) {
  380.       this._listener.onImportComplete(this._targetList,
  381.                                       this._totalImported,
  382.                                       this._totalDups,
  383.                                       this._otherDrops,
  384.                                       this._totalInserted,
  385.                                       this._otherDrops);
  386.     }
  387.  
  388.     // and reset references we do not need anymore, coz leaks suck
  389.     this._importInProgress = false;
  390.     this._targetList = null;
  391.     this._scanList = null;
  392.     this._window = null;
  393.     this._listener = null;
  394.     this._mainLibrary = null;
  395.   },
  396.  
  397.   QueryInterface: XPCOMUtils.generateQI([Ci.sbIURIImportService])
  398. };
  399.  
  400. //------------------------------------------------------------------------------
  401. // XPCOM Registration
  402.  
  403. sbURIImportService.prototype.classDescription = 
  404.   "Songbird URI Import Service";
  405. sbURIImportService.prototype.classID =
  406.   Components.ID("{CC435D34-F76A-458F-B786-FAF897CA69BD}");
  407. sbURIImportService.prototype.contractID =
  408.   "@songbirdnest.com/uri-import-service;1";
  409.  
  410. function NSGetModule(compMgr, fileSpec) {
  411.   return XPCOMUtils.generateModule([sbURIImportService]);
  412. }
  413.  
  414.