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

  1. // JScript source code
  2. /*
  3.  *=BEGIN SONGBIRD GPL
  4.  *
  5.  * This file is part of the Songbird web player.
  6.  *
  7.  * Copyright(c) 2005-2011 POTI, Inc.
  8.  * http://www.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. var Cc = Components.classes;
  27. var Ci = Components.interfaces;
  28. var Cr = Components.results;
  29. var Cu = Components.utils;
  30.  
  31. Cu.import("resource://app/jsmodules/ArrayConverter.jsm");
  32. Cu.import("resource://app/jsmodules/DropHelper.jsm");
  33. Cu.import("resource://app/jsmodules/kPlaylistCommands.jsm");
  34. Cu.import("resource://app/jsmodules/sbAddToPlaylist.jsm");
  35. Cu.import("resource://app/jsmodules/sbAddToDevice.jsm");
  36. Cu.import("resource://app/jsmodules/sbAddToLibrary.jsm");
  37. Cu.import("resource://app/jsmodules/sbCoverHelper.jsm");
  38. Cu.import("resource://app/jsmodules/sbLibraryUtils.jsm");
  39. Cu.import("resource://app/jsmodules/sbProperties.jsm");
  40. Cu.import("resource://app/jsmodules/SBJobUtils.jsm");
  41. Cu.import("resource://app/jsmodules/SBUtils.jsm");
  42. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  43.  
  44. const WEB_PLAYLIST_CONTEXT      = "webplaylist";
  45. const WEB_PLAYLIST_TABLE        = "webplaylist";
  46. const WEB_PLAYLIST_TABLE_NAME   = "&device.webplaylist";
  47. const WEB_PLAYLIST_LIBRARY_NAME = "&device.weblibrary";
  48.  
  49. function SelectionUnwrapper(selection) {
  50.   this._selection = selection;
  51. }
  52.  
  53. SelectionUnwrapper.prototype = {
  54.   _selection: null,
  55.  
  56.   hasMoreElements : function() {
  57.     return this._selection.hasMoreElements();
  58.   },
  59.  
  60.   getNext : function() {
  61.     var item = this._selection.getNext().mediaItem;
  62.     item.setProperty(SBProperties.downloadStatusTarget,
  63.                      item.library.guid + "," + item.guid);
  64.     return item;
  65.   },
  66.  
  67.   QueryInterface : function(iid) {
  68.     if (iid.equals(Ci.nsISimpleEnumerator) ||
  69.         iid.equals(Ci.nsISupports))
  70.       return this;
  71.     throw Cr.NS_NOINTERFACE;
  72.   }
  73. }
  74.  
  75. function PublicPlaylistCommands() {
  76.   this.m_mgr = Components.
  77.     classes["@songbirdnest.com/Songbird/PlaylistCommandsManager;1"]
  78.     .getService(Ci.sbIPlaylistCommandsManager);
  79.  
  80.   var obs = Cc["@mozilla.org/observer-service;1"]
  81.               .getService(Ci.nsIObserverService);
  82.   obs.addObserver(this, "final-ui-startup", false);
  83. }
  84.  
  85. PublicPlaylistCommands.prototype.constructor = PublicPlaylistCommands;
  86.  
  87. PublicPlaylistCommands.prototype = {
  88.  
  89.   classDescription: "Songbird Public Playlist Commands",
  90.   classID:          Components.ID("{1126ee77-2d85-4f79-a07a-b014da404e53}"),
  91.   contractID:       "@songbirdnest.com/Songbird/PublicPlaylistCommands;1",
  92.  
  93.   m_mgr                           : null,
  94.  
  95.   m_defaultCommands               : null,
  96.   m_webPlaylistCommands           : null,
  97.   m_webMediaHistoryToolbarCommands: null,
  98.   m_smartPlaylistsCommands        : null,
  99.   m_downloadCommands              : null,
  100.   m_downloadToolbarCommands       : null,
  101.   m_downloadCommandsServicePane   : null,
  102.   m_serviceTreeDefaultCommands    : null,
  103.   m_deviceLibraryCommands         : null,
  104.   m_cdDeviceLibraryCommands       : null,
  105.   m_playQueueCommands             : null,
  106.   m_playQueueLibraryCommands      : null,
  107.  
  108.   // Define various playlist commands, they will be exposed to the playlist commands
  109.   // manager so that they can later be retrieved and concatenated into bigger
  110.   // playlist commands objects.
  111.  
  112.   // Commands that act on playlist items
  113.   m_cmd_Play                      : null, // play the selected track
  114.   m_cmd_Pause                     : null, // pause the selected track
  115.   m_cmd_Remove                    : null, // remove the selected track(s)
  116.   m_cmd_Edit                      : null, // edit the selected track(s)
  117.   m_cmd_Download                  : null, // download the selected track(s)
  118.   m_cmd_Rescan                    : null, // rescan the selected track(s)
  119.   m_cmd_Reveal                    : null, // reveal the selected track
  120.   m_cmd_CopyTrackLocation         : null, // copy the select track(s) location(s)
  121.   m_cmd_ShowDownloadPlaylist      : null, // switch the browser to show the download playlist
  122.   m_cmd_PauseResumeDownload       : null, // auto-switching pause/resume track download
  123.   m_cmd_CleanUpDownloads          : null, // clean up completed download items
  124.   m_cmd_ClearHistory              : null, // clear the web media history
  125.   m_cmd_UpdateSmartPlaylist       : null, // update the smart playlist
  126.   m_cmd_EditSmartPlaylist         : null, // edit  the smart playlist properties
  127.   m_cmd_SmartPlaylistSep          : null, // a separator (its own object for visible cb)
  128.   m_cmd_LookupCDInfo              : null, // look up cd information
  129.   m_cmd_CheckAll                  : null, // check all
  130.   m_cmd_UncheckAll                : null, // uncheck all
  131.  
  132.   m_cmd_QueueNext                 : null, // add to next position in play queue
  133.   m_cmd_QueueLast                 : null, // add to last position in play queue
  134.  
  135.   // Commands that act on playlist themselves
  136.   m_cmd_list_Play                 : null, // play the selected playlist
  137.   m_cmd_list_Remove               : null, // remove the selected playlist
  138.   m_cmd_list_Rename               : null, // rename the selected playlist
  139.   m_cmd_list_QueueNext            : null, // add all contents of the selected
  140.                                           // playlist to next position in queue
  141.   m_cmd_list_QueueLast            : null, // add all contents of the selected
  142.                                           // playlist to last position in queue
  143.  
  144.   // Play queue library commands
  145.   m_cmd_playqueue_SaveToPlaylist  : null,
  146.   m_cmd_playqueue_ClearHistory    : null,
  147.   m_cmd_playqueue_ClearAll        : null,
  148.  
  149.   m_downloadListGuid              : null,
  150.  
  151.   // ==========================================================================
  152.   // INIT
  153.   // ==========================================================================
  154.   initCommands: function() {
  155.     try {
  156.       if (this.m_mgr.request(kPlaylistCommands.MEDIAITEM_DEFAULT)) {
  157.         // already initialized ! bail out !
  158.         return;
  159.       }
  160.  
  161.       // Add an observer for the application shutdown event, so that we can
  162.       // shutdown our commands
  163.  
  164.       var obs = Cc["@mozilla.org/observer-service;1"]
  165.                   .getService(Ci.nsIObserverService);
  166.       obs.removeObserver(this, "final-ui-startup");
  167.       obs.addObserver(this, "quit-application", false);
  168.  
  169.       // --------------------------------------------------------------------------
  170.  
  171.       var prefs = Cc["@mozilla.org/preferences-service;1"]
  172.                     .getService(Ci.nsIPrefBranch2);
  173.  
  174.       var ddh =
  175.         Components.classes["@songbirdnest.com/Songbird/DownloadDeviceHelper;1"]
  176.                   .getService(Components.interfaces.sbIDownloadDeviceHelper);
  177.       var downloadMediaList = ddh.getDownloadMediaList();
  178.  
  179.       // We save this rather than getting it again because we need to remove
  180.       // by the same id. If we re-fetch it, we might get a different GUID -
  181.       // not in the actual app, because the download media list doesn't just
  182.       // go away, but in unit tests that clear the library.
  183.       if (downloadMediaList)
  184.         this.m_downloadListGuid = downloadMediaList.guid;
  185.       else
  186.         this.m_downloadListGuid = "";
  187.  
  188.  
  189.       // --------------------------------------------------------------------------
  190.  
  191.       // Build playlist command actions
  192.  
  193.       // --------------------------------------------------------------------------
  194.       // The PLAY button is made of two commands, one that is always there for
  195.       // all instantiators, the other that is only created by the shortcuts
  196.       // instantiator. This makes one toolbar button and menu item, and two
  197.       // shortcut keys.
  198.       // --------------------------------------------------------------------------
  199.  
  200.       const PlaylistCommandsBuilder = new Components.
  201.         Constructor("@songbirdnest.com/Songbird/PlaylistCommandsBuilder;1",
  202.                     "sbIPlaylistCommandsBuilder", "init");
  203.  
  204.       this.m_cmd_Play = new PlaylistCommandsBuilder("play-default_download_webplaylist_playqueue-cmd");
  205.  
  206.       // The first item, always created
  207.       this.m_cmd_Play.appendAction(null,
  208.                                    "library_cmd_play",
  209.                                    "&command.play",
  210.                                    "&command.tooltip.play",
  211.                                    plCmd_Play_TriggerCallback);
  212.  
  213.       this.m_cmd_Play.setCommandShortcut(null,
  214.                                          "library_cmd_play",
  215.                                          "&command.shortcut.key.play",
  216.                                          "&command.shortcut.keycode.play",
  217.                                          "&command.shortcut.modifiers.play",
  218.                                          true);
  219.  
  220.       this.m_cmd_Play.setCommandEnabledCallback(null,
  221.                                                 "library_cmd_play",
  222.                                                 plCmd_IsAnyTrackSelected);
  223.  
  224.       this.m_cmd_Play.setCommandVisibleCallback(null,
  225.                                                 "library_cmd_play",
  226.                                                 plCmd_Play_VisibleCallback);
  227.  
  228.       // The second item, only created by the keyboard shortcuts instantiator
  229.       this.m_cmd_Play.appendAction(null,
  230.                                    "library_cmd_play2",
  231.                                    "&command.play",
  232.                                    "&command.tooltip.play",
  233.                                    plCmd_Play_TriggerCallback);
  234.  
  235.       this.m_cmd_Play.setCommandShortcut(null,
  236.                                          "library_cmd_play2",
  237.                                          "&command.shortcut.key.altplay",
  238.                                          "&command.shortcut.keycode.altplay",
  239.                                          "&command.shortcut.modifiers.altplay",
  240.                                          true);
  241.  
  242.       this.m_cmd_Play.setCommandEnabledCallback(null,
  243.                                                 "library_cmd_play2",
  244.                                                 plCmd_IsAnyTrackSelected);
  245.  
  246.       this.m_cmd_Play.setCommandVisibleCallback(null,
  247.                                                 "library_cmd_play2",
  248.                                                 plCmd_IsShortcutsInstantiator);
  249.  
  250.       this.m_cmd_Pause = new PlaylistCommandsBuilder("pause-default_download_webplaylist_playqueue-cmd");
  251.  
  252.       this.m_cmd_Pause.appendAction(null,
  253.                                     "library_cmd_pause",
  254.                                     "&command.pause",
  255.                                     "&command.tooltip.pause",
  256.                                     plCmd_Pause_TriggerCallback);
  257.  
  258.       this.m_cmd_Pause.setCommandVisibleCallback(null,
  259.                                                  "library_cmd_pause",
  260.                                                  plCmd_Pause_VisibleCallback);
  261.  
  262.       // --------------------------------------------------------------------------
  263.       // The REMOVE button, like the play button, is made of two commands, one that
  264.       // is always there for all instantiators, the other that is only created by
  265.       // the shortcuts instantiator. This makes one toolbar button and menu item,
  266.       // and two shortcut keys.
  267.       // --------------------------------------------------------------------------
  268.  
  269.       this.m_cmd_Remove = new PlaylistCommandsBuilder("remove-default_download_device_webplaylist_playqueue-cmd");
  270.  
  271.       // The first item, always created
  272.       this.m_cmd_Remove.appendAction(null,
  273.                                      "library_cmd_remove",
  274.                                      "&command.remove",
  275.                                      "&command.tooltip.remove",
  276.                                      plCmd_Remove_TriggerCallback);
  277.  
  278.       this.m_cmd_Remove.setCommandShortcut(null,
  279.                                            "library_cmd_remove",
  280.                                            "&command.shortcut.key.remove",
  281.                                            "&command.shortcut.keycode.remove",
  282.                                            "&command.shortcut.modifiers.remove",
  283.                                            true);
  284.  
  285.       this.m_cmd_Remove.setCommandEnabledCallback(null,
  286.                                                   "library_cmd_remove",
  287.                                                   plCmd_AND(
  288.                                                     plCmd_IsAnyTrackSelected,
  289.                                                     plCmd_CanModifyPlaylistContent));
  290.  
  291.       // The second item, only created by the keyboard shortcuts instantiator,
  292.       // and only for the mac.
  293.       var sysInfo = Components.classes["@mozilla.org/system-info;1"]
  294.                     .getService(Components.interfaces.nsIPropertyBag2);
  295.       if ( sysInfo.getProperty("name") == "Darwin" ) {
  296.         this.m_cmd_Remove.appendAction(null,
  297.                                        "library_cmd_remove2",
  298.                                        "&command.remove",
  299.                                        "&command.tooltip.remove",
  300.                                        plCmd_Remove_TriggerCallback);
  301.  
  302.         this.m_cmd_Remove.setCommandShortcut(null,
  303.                                              "library_cmd_remove2",
  304.                                              "&command.shortcut.key.altremove",
  305.                                              "&command.shortcut.keycode.altremove",
  306.                                              "&command.shortcut.modifiers.altremove",
  307.                                              true);
  308.  
  309.         this.m_cmd_Remove.setCommandEnabledCallback(null,
  310.                                                     "library_cmd_remove2",
  311.                                                     plCmd_AND(
  312.                                                       plCmd_IsAnyTrackSelected,
  313.                                                       plCmd_CanModifyPlaylistContent));
  314.  
  315.         this.m_cmd_Remove.setCommandVisibleCallback(null,
  316.                                                     "library_cmd_remove2",
  317.                                                     plCmd_IsShortcutsInstantiator);
  318.       }
  319.  
  320.       // --------------------------------------------------------------------------
  321.       // The EDIT button
  322.       // --------------------------------------------------------------------------
  323.  
  324.       this.m_cmd_Edit = new PlaylistCommandsBuilder("edit-default_device_cddevice-cmd");
  325.  
  326.       this.m_cmd_Edit.appendAction(null,
  327.                                    "library_cmd_edit",
  328.                                    "&command.edit",
  329.                                    "&command.tooltip.edit",
  330.                                    plCmd_Edit_TriggerCallback);
  331.  
  332.       this.m_cmd_Edit.setCommandShortcut(null,
  333.                                          "library_cmd_edit",
  334.                                          "&command.shortcut.key.edit",
  335.                                          "&command.shortcut.keycode.edit",
  336.                                          "&command.shortcut.modifiers.edit",
  337.                                          true);
  338.  
  339.       this.m_cmd_Edit.setCommandEnabledCallback(null,
  340.                                                 "library_cmd_edit",
  341.                                                 plCmd_IsAnyTrackSelected);
  342.  
  343.       // --------------------------------------------------------------------------
  344.       // The DOWNLOAD button
  345.       // --------------------------------------------------------------------------
  346.  
  347.       this.m_cmd_Download = new PlaylistCommandsBuilder("download-webplaylist-cmd");
  348.  
  349.       this.m_cmd_Download.appendAction(null,
  350.                                        "library_cmd_download",
  351.                                        "&command.download",
  352.                                        "&command.tooltip.download",
  353.                                        plCmd_Download_TriggerCallback);
  354.  
  355.       this.m_cmd_Download.setCommandShortcut(null,
  356.                                              "library_cmd_download",
  357.                                              "&command.shortcut.key.download",
  358.                                              "&command.shortcut.keycode.download",
  359.                                              "&command.shortcut.modifiers.download",
  360.                                              true);
  361.  
  362.       this.m_cmd_Download.setCommandEnabledCallback(null,
  363.                                                     "library_cmd_download",
  364.                                                     plCmd_Download_EnabledCallback);
  365.  
  366.       // --------------------------------------------------------------------------
  367.       // The RESCAN button
  368.       // --------------------------------------------------------------------------
  369.  
  370.  
  371.       this.m_cmd_Rescan = new PlaylistCommandsBuilder("rescan-default_playqueue-cmd");
  372.  
  373.       this.m_cmd_Rescan.appendAction(null,
  374.                                      "library_cmd_rescan",
  375.                                      "&command.rescan",
  376.                                      "&command.tooltip.rescan",
  377.                                      plCmd_Rescan_TriggerCallback);
  378.  
  379.       this.m_cmd_Rescan.setCommandShortcut(null,
  380.                                            "library_cmd_rescan",
  381.                                            "&command.shortcut.key.rescan",
  382.                                            "&command.shortcut.keycode.rescan",
  383.                                            "&command.shortcut.modifiers.rescan",
  384.                                            true);
  385.  
  386.       this.m_cmd_Rescan.setCommandEnabledCallback(null,
  387.                                                   "library_cmd_rescan",
  388.                                                   plCmd_IsAnyTrackSelected);
  389.  
  390.       this.m_cmd_Rescan.setCommandVisibleCallback(null,
  391.                                                   "library_cmd_rescan",
  392.                                                   plCmd_IsRescanItemEnabled);
  393.  
  394.       // --------------------------------------------------------------------------
  395.       // The REVEAL button
  396.       // --------------------------------------------------------------------------
  397.  
  398.  
  399.       this.m_cmd_Reveal = new PlaylistCommandsBuilder("reveal-default_device_playqueue-cmd");
  400.  
  401.       this.m_cmd_Reveal.appendAction(null,
  402.                                      "library_cmd_reveal",
  403.                                      "&command.reveal",
  404.                                      "&command.tooltip.reveal",
  405.                                      plCmd_Reveal_TriggerCallback);
  406.  
  407.       this.m_cmd_Reveal.setCommandShortcut(null,
  408.                                            "library_cmd_reveal",
  409.                                            "&command.shortcut.key.reveal",
  410.                                            "&command.shortcut.keycode.reveal",
  411.                                            "&command.shortcut.modifiers.reveal",
  412.                                            true);
  413.  
  414.       this.m_cmd_Reveal.setCommandEnabledCallback(null,
  415.                                                   "library_cmd_reveal",
  416.                                                   plCmd_isSelectionRevealable);
  417.  
  418.       // --------------------------------------------------------------------------
  419.       // The COPY TRACK LOCATION button
  420.       // --------------------------------------------------------------------------
  421.  
  422.       this.m_cmd_CopyTrackLocation = new PlaylistCommandsBuilder
  423.                                          ("copylocation-webplaylist-cmd");
  424.  
  425.       this.m_cmd_CopyTrackLocation.appendAction(null,
  426.                                                 "library_cmd_copylocation",
  427.                                                 "&command.copylocation",
  428.                                                 "&command.tooltip.copylocation",
  429.                                                 plCmd_CopyTrackLocation_TriggerCallback);
  430.  
  431.       this.m_cmd_CopyTrackLocation.setCommandShortcut(null,
  432.                                                       "library_cmd_copylocation",
  433.                                                       "&command.shortcut.key.copylocation",
  434.                                                       "&command.shortcut.keycode.copylocation",
  435.                                                       "&command.shortcut.modifiers.copylocation",
  436.                                                       true);
  437.  
  438.       this.m_cmd_CopyTrackLocation.setCommandEnabledCallback(null,
  439.                                                              "library_cmd_copylocation",
  440.                                                              plCmd_IsAnyTrackSelected);
  441.  
  442.       // --------------------------------------------------------------------------
  443.       // The CLEAR HISTORY button
  444.       // --------------------------------------------------------------------------
  445.  
  446.       this.m_cmd_ClearHistory = new PlaylistCommandsBuilder
  447.                                     ("clearhistory-webhistory-cmd");
  448.  
  449.       this.m_cmd_ClearHistory.appendAction
  450.                                         (null,
  451.                                          "library_cmd_clearhistory",
  452.                                          "&command.clearhistory",
  453.                                          "&command.tooltip.clearhistory",
  454.                                          plCmd_ClearHistory_TriggerCallback);
  455.  
  456.       this.m_cmd_ClearHistory.setCommandShortcut
  457.                                   (null,
  458.                                    "library_cmd_clearhistory",
  459.                                    "&command.shortcut.key.clearhistory",
  460.                                    "&command.shortcut.keycode.clearhistory",
  461.                                    "&command.shortcut.modifiers.clearhistory",
  462.                                    true);
  463.  
  464.       this.m_cmd_ClearHistory.setCommandEnabledCallback
  465.                                                 (null,
  466.                                                  "library_cmd_clearhistory",
  467.                                                  plCmd_WebMediaHistoryHasItems);
  468.  
  469.       // --------------------------------------------------------------------------
  470.       // The SHOW DOWNLOAD PLAYLIST button
  471.       // --------------------------------------------------------------------------
  472.  
  473.       this.m_cmd_ShowDownloadPlaylist = new PlaylistCommandsBuilder
  474.                                             ("showdl-webplaylist-cmd");
  475.  
  476.       this.m_cmd_ShowDownloadPlaylist.appendAction(null,
  477.                                                   "library_cmd_showdlplaylist",
  478.                                                   "&command.showdlplaylist",
  479.                                                   "&command.tooltip.showdlplaylist",
  480.                                                   plCmd_ShowDownloadPlaylist_TriggerCallback);
  481.  
  482.       this.m_cmd_ShowDownloadPlaylist.setCommandShortcut(null,
  483.                                                         "library_cmd_showdlplaylist",
  484.                                                         "&command.shortcut.key.showdlplaylist",
  485.                                                         "&command.shortcut.keycode.showdlplaylist",
  486.                                                         "&command.shortcut.modifiers.showdlplaylist",
  487.                                                         true);
  488.  
  489.       this.m_cmd_ShowDownloadPlaylist.setCommandVisibleCallback(null,
  490.                                                                 "library_cmd_showdlplaylist",
  491.                                                                 plCmd_ContextHasBrowser);
  492.  
  493.       // --------------------------------------------------------------------------
  494.       // The PAUSE/RESUME DOWNLOAD button
  495.       // --------------------------------------------------------------------------
  496.  
  497.       this.m_cmd_PauseResumeDownload = new PlaylistCommandsBuilder
  498.                                            ("pauseresume-download-cmd");
  499.  
  500.       this.m_cmd_PauseResumeDownload.appendAction(null,
  501.                                                   "library_cmd_pause",
  502.                                                   "&command.pausedl",
  503.                                                   "&command.tooltip.pause",
  504.                                                   plCmd_PauseResumeDownload_TriggerCallback);
  505.  
  506.       this.m_cmd_PauseResumeDownload.setCommandShortcut(null,
  507.                                                         "library_cmd_pause",
  508.                                                         "&command.shortcut.key.pause",
  509.                                                         "&command.shortcut.keycode.pause",
  510.                                                         "&command.shortcut.modifiers.pause",
  511.                                                         true);
  512.  
  513.       this.m_cmd_PauseResumeDownload.setCommandVisibleCallback(null,
  514.                                                       "library_cmd_pause",
  515.                                                       plCmd_IsDownloadingOrNotActive);
  516.  
  517.       this.m_cmd_PauseResumeDownload.setCommandEnabledCallback(null,
  518.                                                       "library_cmd_pause",
  519.                                                       plCmd_IsDownloadActive);
  520.  
  521.       this.m_cmd_PauseResumeDownload.appendAction(null,
  522.                                                   "library_cmd_resume",
  523.                                                   "&command.resumedl",
  524.                                                   "&command.tooltip.resume",
  525.                                                   plCmd_PauseResumeDownload_TriggerCallback);
  526.  
  527.       this.m_cmd_PauseResumeDownload.setCommandShortcut(null,
  528.                                                         "library_cmd_resume",
  529.                                                         "&command.shortcut.key.resume",
  530.                                                         "&command.shortcut.keycode.resume",
  531.                                                         "&command.shortcut.modifiers.resume",
  532.                                                         true);
  533.  
  534.       this.m_cmd_PauseResumeDownload.setCommandVisibleCallback(null,
  535.                                                       "library_cmd_resume",
  536.                                                       plCmd_IsDownloadPaused);
  537.  
  538.       // --------------------------------------------------------------------------
  539.       // The CLEAN UP DOWNLOADS button
  540.       // --------------------------------------------------------------------------
  541.  
  542.       this.m_cmd_CleanUpDownloads = new PlaylistCommandsBuilder
  543.                                         ("cleanup-download-cmd");
  544.  
  545.       this.m_cmd_CleanUpDownloads.appendAction
  546.                                         (null,
  547.                                          "library_cmd_cleanupdownloads",
  548.                                          "&command.cleanupdownloads",
  549.                                          "&command.tooltip.cleanupdownloads",
  550.                                          plCmd_CleanUpDownloads_TriggerCallback);
  551.  
  552.       this.m_cmd_CleanUpDownloads.setCommandShortcut
  553.                                   (null,
  554.                                    "library_cmd_cleanupdownloads",
  555.                                    "&command.shortcut.key.cleanupdownloads",
  556.                                    "&command.shortcut.keycode.cleanupdownloads",
  557.                                    "&command.shortcut.modifiers.cleanupdownloads",
  558.                                    true);
  559.  
  560.       this.m_cmd_CleanUpDownloads.setCommandEnabledCallback
  561.                                                 (null,
  562.                                                  "library_cmd_cleanupdownloads",
  563.                                                  plCmd_DownloadHasCompletedItems);
  564.  
  565.       // -----------------------------------------------------------------------
  566.       // The Play Playlist action
  567.       // -----------------------------------------------------------------------
  568.  
  569.       this.m_cmd_list_Play = new PlaylistCommandsBuilder("play-servicetree-cmd");
  570.  
  571.       this.m_cmd_list_Play.appendAction(null,
  572.                                         "playlist_cmd_play",
  573.                                         "&command.playlist.play",
  574.                                         "&command.tooltip.playlist.play",
  575.                                         plCmd_PlayPlaylist_TriggerCallback);
  576.  
  577.       this.m_cmd_list_Play.setCommandShortcut(null,
  578.                                     "playlist_cmd_play",
  579.                                     "&command.playlist.shortcut.key.play",
  580.                                     "&command.playlist.shortcut.keycode.play",
  581.                                     "&command.playlist.shortcut.modifiers.play",
  582.                                     true);
  583.  
  584.       // disable the command for empty playlists.
  585.       this.m_cmd_list_Play.setCommandEnabledCallback(null,
  586.                                                      "playlist_cmd_play",
  587.                                                      plCmd_IsNotEmptyPlaylist);
  588.  
  589.       // --------------------------------------------------------------------------
  590.       // The Remove Playlist action
  591.       // --------------------------------------------------------------------------
  592.  
  593.       this.m_cmd_list_Remove = new PlaylistCommandsBuilder("remove-servicetree-cmd");
  594.  
  595.       this.m_cmd_list_Remove.appendAction(null,
  596.                                          "playlist_cmd_remove",
  597.                                          "&command.playlist.remove",
  598.                                          "&command.tooltip.playlist.remove",
  599.                                          plCmd_RemoveList_TriggerCallback);
  600.  
  601.       this.m_cmd_list_Remove.setCommandShortcut(null,
  602.                                                "playlist_cmd_remove",
  603.                                                "&command.playlist.shortcut.key.remove",
  604.                                                "&command.playlist.shortcut.keycode.remove",
  605.                                                "&command.playlist.shortcut.modifiers.remove",
  606.                                                true);
  607.  
  608.       // disable the command for readonly playlists.
  609.       this.m_cmd_list_Remove.setCommandEnabledCallback
  610.                                                 (null,
  611.                                                  "playlist_cmd_remove",
  612.                                                  plCmd_CanModifyPlaylist);
  613.  
  614.       // --------------------------------------------------------------------------
  615.       // The Rename Playlist action
  616.       // --------------------------------------------------------------------------
  617.  
  618.       this.m_cmd_list_Rename = new PlaylistCommandsBuilder("rename-servicetree-cmd");
  619.  
  620.       this.m_cmd_list_Rename.appendAction(null,
  621.                                          "playlist_cmd_rename",
  622.                                          "&command.playlist.rename",
  623.                                          "&command.tooltip.playlist.rename",
  624.                                          plCmd_RenameList_TriggerCallback);
  625.  
  626.       this.m_cmd_list_Rename.setCommandShortcut(null,
  627.                                                "playlist_cmd_rename",
  628.                                                "&command.playlist.shortcut.key.rename",
  629.                                                "&command.playlist.shortcut.keycode.rename",
  630.                                                "&command.playlist.shortcut.modifiers.rename",
  631.                                                true);
  632.  
  633.       // disable the command for readonly playlists.
  634.       this.m_cmd_list_Rename.setCommandEnabledCallback(null,
  635.                                                        "playlist_cmd_rename",
  636.                                                        plCmd_CanModifyPlaylist);
  637.  
  638.       // --------------------------------------------------------------------------
  639.       // The QueueNext Playlist action
  640.       // --------------------------------------------------------------------------
  641.  
  642.       this.m_cmd_list_QueueNext = new PlaylistCommandsBuilder("queuenext-servicetree-cmd");
  643.  
  644.       this.m_cmd_list_QueueNext.appendAction(null,
  645.                                              "playlist_cmd_queuenext",
  646.                                              "&command.playlist.queuenext",
  647.                                              "&command.tooltip.playlist.queuenext",
  648.                                              plCmd_QueueListNext_TriggerCallback);
  649.  
  650.       this.m_cmd_list_QueueNext.setCommandShortcut(null,
  651.                                                    "playlist_cmd_queuenext",
  652.                                                    "&command.playlist.shortcut.key.queuenext",
  653.                                                    "&command.playlist.shortcut.keycode.queuenext",
  654.                                                    "&command.playlist.shortcut.modifiers.queuenext",
  655.                                                    true);
  656.  
  657.       this.m_cmd_list_QueueNext.setCommandVisibleCallback(null,
  658.                                                           "playlist_cmd_queuenext",
  659.                                                           plCmd_CanQueuePlaylist);
  660.  
  661.       // disable the command for empty playlists.
  662.       this.m_cmd_list_QueueNext.setCommandEnabledCallback(null,
  663.                                                           "playlist_cmd_queuenext",
  664.                                                           plCmd_ListContextMenuQueueEnabled);
  665.  
  666.       // --------------------------------------------------------------------------
  667.       // The QueueLast Playlist action
  668.       // --------------------------------------------------------------------------
  669.  
  670.       this.m_cmd_list_QueueLast = new PlaylistCommandsBuilder("queuelast-servicetree-cmd");
  671.  
  672.       this.m_cmd_list_QueueLast.appendAction(null,
  673.                                              "playlist_cmd_queuelast",
  674.                                              "&command.playlist.queuelast",
  675.                                              "&command.tooltip.playlist.queuelast",
  676.                                              plCmd_QueueListLast_TriggerCallback);
  677.  
  678.       this.m_cmd_list_QueueLast.setCommandShortcut(null,
  679.                                                    "playlist_cmd_queuelast",
  680.                                                    "&command.playlist.shortcut.key.queuelast",
  681.                                                    "&command.playlist.shortcut.keycode.queuelast",
  682.                                                    "&command.playlist.shortcut.modifiers.queuelast",
  683.                                                    true);
  684.  
  685.       this.m_cmd_list_QueueLast.setCommandVisibleCallback(null,
  686.                                                           "playlist_cmd_queuelast",
  687.                                                           plCmd_CanQueuePlaylist);
  688.  
  689.       // disable the command for empty playlists.
  690.       this.m_cmd_list_QueueLast.setCommandEnabledCallback(null,
  691.                                                           "playlist_cmd_queuelast",
  692.                                                           plCmd_ListContextMenuQueueEnabled);
  693.  
  694.       // --------------------------------------------------------------------------
  695.       // The Get Artwork action
  696.       // --------------------------------------------------------------------------
  697.  
  698.       this.m_cmd_GetArtwork = new PlaylistCommandsBuilder("getartwork-default-cmd");
  699.  
  700.       this.m_cmd_GetArtwork.appendAction(null,
  701.                                          "library_cmd_getartwork",
  702.                                          "&command.getartwork",
  703.                                          "&command.tooltip.getartwork",
  704.                                          plCmd_GetArtwork_TriggerCallback);
  705.  
  706.       this.m_cmd_GetArtwork.setCommandShortcut(null,
  707.                                                "library_cmd_getartwork",
  708.                                                "&command.shortcut.key.getartwork",
  709.                                                "&command.shortcut.keycode.getartwork",
  710.                                                "&command.shortcut.modifiers.getartwork",
  711.                                                true);
  712.  
  713.       this.m_cmd_GetArtwork.setCommandVisibleCallback(null,
  714.                                                       "library_cmd_getartwork",
  715.                                                       plCmd_IsAnyAudioSelected);
  716.  
  717.       this.m_cmd_GetArtwork.setCommandEnabledCallback(null,
  718.                                                       "library_cmd_getartwork",
  719.                                                       plCmd_IsAnyTrackSelected);
  720.  
  721.       // --------------------------------------------------------------------------
  722.       // The 'Show Device Only' and 'Show All On Device' actions for MSC & MTP
  723.       // --------------------------------------------------------------------------
  724.       // A command object for devices to hold commands that show in the toolbar
  725.       this.m_cmd_DeviceToolbarCmds =
  726.         new PlaylistCommandsBuilder("device_cmds_toolbar");
  727.  
  728.       // A command to show items only on the device
  729.       this.m_cmd_ShowOnlyOnDevice =
  730.         new PlaylistCommandsBuilder("device_cmd_showdeviceonly");
  731.  
  732.       this.m_cmd_ShowOnlyOnDevice.appendAction
  733.                                (null,
  734.                                 "device_cmd_showdeviceonly",
  735.                                 "&device.command.show_only_on_device",
  736.                                 "",
  737.                                 plCmd_ShowOnlyOnDevice_TriggerCallback);
  738.  
  739.       // Show the 'device only' command only when we aren't already filtering
  740.       this.m_cmd_ShowOnlyOnDevice
  741.           .setVisibleCallback(plCmd_ShowOnlyOnDevice_VisibleCallback);
  742.  
  743.       this.m_cmd_DeviceToolbarCmds.appendPlaylistCommands
  744.                                   (null,
  745.                                    "device_cmdobj_showdeviceonly",
  746.                                    this.m_cmd_ShowOnlyOnDevice);
  747.  
  748.       // A command to shall all items on the device
  749.       this.m_cmd_ShowAllOnDevice =
  750.         new PlaylistCommandsBuilder("device_cmd_showallondevice");
  751.  
  752.       this.m_cmd_ShowAllOnDevice.appendAction
  753.                                 (null,
  754.                                  "device_cmd_showallondevice",
  755.                                  "&device.command.show_all_on_device",
  756.                                  "",
  757.                                  plCmd_ShowAllOnDevice_TriggerCallback);
  758.  
  759.  
  760.       this.m_cmd_DeviceToolbarCmds.appendPlaylistCommands
  761.                                   (null,
  762.                                    "device_cmdobj_showallondevice",
  763.                                    this.m_cmd_ShowAllOnDevice);
  764.  
  765.       // Show the 'show all' command when we are filtering for device only
  766.       this.m_cmd_ShowAllOnDevice
  767.           .setVisibleCallback(plCmd_ShowAllOnDevice_VisibleCallback);
  768.  
  769.       // Publish this command so that it can be registered to the device
  770.       // library when a device is mounted.
  771.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_DEVICE_LIBRARY_TOOLBAR,
  772.                          this.m_cmd_DeviceToolbarCmds);
  773.  
  774.       // --------------------------------------------------------------------------
  775.       // The Lookup CD Info action
  776.       // --------------------------------------------------------------------------
  777.  
  778.       this.m_cmd_LookupCDInfo = new PlaylistCommandsBuilder("lookupcd-cddevice-cmd");
  779.  
  780.       this.m_cmd_LookupCDInfo.appendAction(null,
  781.                                            "library_cmd_lookupcdinfo",
  782.                                            "&command.lookupcdinfo",
  783.                                            "&command.tooltip.lookupcdinfo",
  784.                                            plCmd_LookupCDInfo_TriggerCallback);
  785.  
  786.       this.m_cmd_LookupCDInfo.setCommandShortcut(null,
  787.                                                  "library_cmd_lookupcdinfo",
  788.                                                  "&command.shortcut.key.lookupcdinfo",
  789.                                                  "&command.shortcut.keycode.lookupcdinfo",
  790.                                                  "&command.shortcut.modifiers.lookupcdinfo",
  791.                                                  true);
  792.       this.m_cmd_LookupCDInfo.setCommandEnabledCallback(null,
  793.                                                         "library_cmd_lookupcdinfo",
  794.                                                         plCmd_NOT(plCmd_IsMediaListReadOnly));
  795.  
  796.       // --------------------------------------------------------------------------
  797.       // Play Queue bundled commands
  798.       // --------------------------------------------------------------------------
  799.  
  800.       this.m_cmd_playqueue_SaveToPlaylist = new PlaylistCommandsBuilder
  801.                                                 ("saveto-playqueue-cmd");
  802.  
  803.       this.m_cmd_playqueue_SaveToPlaylist.appendAction(null,
  804.                                                        "playqueue_cmd_savetoplaylist",
  805.                                                        "&command.queuesavetoplaylist",
  806.                                                        "&command.tooltip.queuesavetoplaylist",
  807.                                                        plCmd_QueueSaveToPlaylist_TriggerCallback);
  808.  
  809.       this.m_cmd_playqueue_SaveToPlaylist.setCommandShortcut(null,
  810.                                                              "playqueue_cmd_savetoplaylist",
  811.                                                              "&command.shortcut.key.queuesavetoplaylist",
  812.                                                              "&command.shortcut.keycode.queuesavetoplaylist",
  813.                                                              "&command.shortcut.modifiers.queuesavetoplaylist",
  814.                                                              true);
  815.  
  816.       this.m_cmd_playqueue_ClearAll = new PlaylistCommandsBuilder
  817.                                           ("clearall-playqueue-cmd");
  818.  
  819.       this.m_cmd_playqueue_ClearAll.appendAction(
  820.                              null,
  821.                              "playqueue_cmd_clearall",
  822.                              "&command.queueclearall",
  823.                              "&command.tooltip.queueclearall",
  824.                              plCmd_QueueClearAll_TriggerCallback);
  825.  
  826.       this.m_cmd_playqueue_ClearAll.setCommandShortcut(
  827.                              null,
  828.                              "playqueue_cmd_clearall",
  829.                              "&command.shortcut.key.queueclearall",
  830.                              "&command.shortcut.keycode.queueclearall",
  831.                              "&command.shortcut.modifiers.queueclearall",
  832.                              true);
  833.  
  834.       this.m_cmd_playqueue_ClearHistory = new PlaylistCommandsBuilder
  835.                                               ("clearhistory-playqueue-cmd");
  836.  
  837.       this.m_cmd_playqueue_ClearHistory.appendSubmenu(
  838.                              null,
  839.                              "playqueue_cmd_clearhistory",
  840.                              null,
  841.                              "&command.tooltip.queueclearhistory",
  842.                              true);
  843.  
  844.       this.m_cmd_playqueue_ClearHistory.appendAction(
  845.                              "playqueue_cmd_clearhistory",
  846.                              "playqueue_cmd_clearhistorymenuitem",
  847.                              "&command.queueclearhistory",
  848.                              "&command.tooltip.queueclearhistory",
  849.                              plCmd_QueueClearHistory_TriggerCallback);
  850.  
  851.       this.m_cmd_playqueue_ClearHistory.setCommandShortcut(
  852.                              "playqueue_cmd_clearhistory",
  853.                              "playqueue_cmd_clearhistorymenuitem",
  854.                              "&command.shortcut.key.queueclearhistory",
  855.                              "&command.shortcut.keycode.queueclearhistory",
  856.                              "&command.shortcut.modifiers.queueclearhistory",
  857.                              true);
  858.  
  859.       // ----------------------------------------------------------------------
  860.       // The Check/Uncheck All actions
  861.       // ----------------------------------------------------------------------
  862.       this.m_cmd_CheckAll = new PlaylistCommandsBuilder("checkall-cddevice-cmd");
  863.       this.m_cmd_CheckAll.appendAction(null,
  864.                                        "library_cmd_checkall",
  865.                                        "&command.checkall",
  866.                                        "&command.tooltip.checkall",
  867.                                        plCmd_CheckAll_TriggerCallback);
  868.       this.m_cmd_CheckAll.setCommandVisibleCallback(
  869.                                        null,
  870.                                        "library_cmd_checkall",
  871.                                        plCmd_CheckAllVisibleCallback);
  872.       this.m_cmd_CheckAll.setCommandEnabledCallback(null,
  873.                                                     "library_cmd_checkall",
  874.                                                     plCmd_NOT(plCmd_IsMediaListReadOnly));
  875.  
  876.       this.m_cmd_UncheckAll = new PlaylistCommandsBuilder("uncheckall-cddevice-cmd");
  877.       this.m_cmd_UncheckAll.appendAction(
  878.                                     null,
  879.                                     "library_cmd_uncheckall",
  880.                                     "&command.uncheckall",
  881.                                     "&command.tooltip.uncheckall",
  882.                                     plCmd_UncheckAll_TriggerCallback);
  883.       this.m_cmd_UncheckAll.setCommandVisibleCallback(null,
  884.                                     "library_cmd_uncheckall",
  885.                                     plCmd_NOT(plCmd_CheckAllVisibleCallback));
  886.       this.m_cmd_UncheckAll.setCommandEnabledCallback(null,
  887.                                                       "library_cmd_uncheckall",
  888.                                                       plCmd_NOT(plCmd_IsMediaListReadOnly));
  889.  
  890.       // -----------------------------------------------------------------------
  891.       // The Queue Next action
  892.       // -----------------------------------------------------------------------
  893.       this.m_cmd_QueueNext = new PlaylistCommandsBuilder("queuenext-default_webplaylist-cmd");
  894.       this.m_cmd_QueueNext.appendAction(null,
  895.                                         "library_cmd_queuenext",
  896.                                         "&command.queuenext",
  897.                                         "&command.tooltip.queuenext",
  898.                                         plCmd_QueueNext_TriggerCallback);
  899.  
  900.       this.m_cmd_QueueNext.setCommandShortcut(null,
  901.                                               "library_cmd_queuenext",
  902.                                               "&command.shortcut.key.queuenext",
  903.                                               "&command.shortcut.keycode.queuenext",
  904.                                               "&command.shortcut.modifiers.queuenext",
  905.                                               true);
  906.  
  907.       this.m_cmd_QueueNext.setCommandEnabledCallback(null,
  908.                                                      "library_cmd_queuenext",
  909.                                                      plCmd_ContextMenuQueueEnabled);
  910.  
  911.       // -----------------------------------------------------------------------
  912.       // The Queue Last action
  913.       // -----------------------------------------------------------------------
  914.       this.m_cmd_QueueLast = new PlaylistCommandsBuilder("queuelast-default_webplaylist-cmd");
  915.       this.m_cmd_QueueLast.appendAction(null,
  916.                                         "library_cmd_queuelast",
  917.                                         "&command.queuelast",
  918.                                         "&command.tooltip.queuelast",
  919.                                         plCmd_QueueLast_TriggerCallback);
  920.  
  921.       this.m_cmd_QueueLast.setCommandShortcut(null,
  922.                                               "library_cmd_queuelast",
  923.                                               "&command.shortcut.key.queuelast",
  924.                                               "&command.shortcut.keycode.queuelast",
  925.                                               "&command.shortcut.modifiers.queuelast",
  926.                                               true);
  927.       this.m_cmd_QueueLast.setCommandEnabledCallback(null,
  928.                                                      "library_cmd_queuelast",
  929.                                                      plCmd_ContextMenuQueueEnabled);
  930.  
  931.       // --------------------------------------------------------------------------
  932.  
  933.       // Publish atomic commands
  934.  
  935.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_PLAY, this.m_cmd_Play);
  936.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_PAUSE, this.m_cmd_Pause);
  937.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_REMOVE, this.m_cmd_Remove);
  938.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_EDIT, this.m_cmd_Edit);
  939.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_DOWNLOAD, this.m_cmd_Download);
  940.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_RESCAN, this.m_cmd_Rescan);
  941.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_REVEAL, this.m_cmd_Reveal);
  942.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_ADDTOPLAYLIST, SBPlaylistCommand_AddToPlaylist);
  943.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_ADDTODEVICE, SBPlaylistCommand_AddToDevice);
  944.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_ADDTOLIBRARY, SBPlaylistCommand_AddToLibrary);
  945.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_COPYTRACKLOCATION, this.m_cmd_CopyTrackLocation);
  946.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_SHOWDOWNLOADPLAYLIST, this.m_cmd_ShowDownloadPlaylist);
  947.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_PAUSERESUMEDOWNLOAD, this.m_cmd_PauseResumeDownload);
  948.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_CLEANUPDOWNLOADS, this.m_cmd_CleanUpDownloads);
  949.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_CLEARHISTORY, this.m_cmd_ClearHistory);
  950.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_GETARTWORK, this.m_cmd_GetArtwork);
  951.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_QUEUENEXT, this.m_cmd_QueueNext);
  952.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_QUEUELAST, this.m_cmd_QueueLast);
  953.  
  954.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_PLAY, this.m_cmd_list_Play);
  955.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_REMOVE, this.m_cmd_list_Remove);
  956.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_RENAME, this.m_cmd_list_Rename);
  957.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_QUEUENEXT, this.m_cmd_list_QueueNext);
  958.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_QUEUELAST, this.m_cmd_list_QueueLast);
  959.  
  960.       // --------------------------------------------------------------------------
  961.       // Construct and publish the main library commands
  962.       // --------------------------------------------------------------------------
  963.  
  964.       this.m_defaultCommands = new PlaylistCommandsBuilder("default_cmds");
  965.  
  966.       this.m_defaultCommands.appendPlaylistCommands(null,
  967.                                                     "library_cmdobj_play",
  968.                                                     this.m_cmd_Play);
  969.  
  970.       this.m_defaultCommands.appendPlaylistCommands(null,
  971.                                                     "library_cmdobj_pause",
  972.                                                     this.m_cmd_Pause);
  973.  
  974.       this.m_defaultCommands.appendPlaylistCommands(null,
  975.                                                     "library_cmdobj_edit",
  976.                                                     this.m_cmd_Edit);
  977.       this.m_defaultCommands.appendPlaylistCommands(null,
  978.                                                     "library_cmdobj_reveal",
  979.                                                     this.m_cmd_Reveal);
  980.       this.m_defaultCommands.appendPlaylistCommands(null,
  981.                                                     "library_cmdobj_getartwork",
  982.                                                     this.m_cmd_GetArtwork);
  983.  
  984.       this.m_defaultCommands.appendSeparator(null, "default_commands_separator_1");
  985.  
  986.       this.m_defaultCommands.appendPlaylistCommands(null,
  987.                                                     "library_cmdobj_addtoplaylist",
  988.                                                     SBPlaylistCommand_AddToPlaylist);
  989.       this.m_defaultCommands.appendPlaylistCommands(null,
  990.                                                     "library_cmdobj_addtodevice",
  991.                                                     SBPlaylistCommand_AddToDevice);
  992.  
  993.       this.m_defaultCommands.appendSeparator(null, "default_commands_separator_2");
  994.  
  995.       this.m_defaultCommands.appendPlaylistCommands(null,
  996.                                                     "library_cmdobj_rescan",
  997.                                                     this.m_cmd_Rescan);
  998.  
  999.       this.m_defaultCommands.appendPlaylistCommands(null,
  1000.                                                     "library_cmdobj_remove",
  1001.                                                     this.m_cmd_Remove);
  1002.  
  1003.       this.m_defaultCommands.appendSeparator(null, "default_commands_separator_3");
  1004.  
  1005.       this.m_defaultCommands.appendPlaylistCommands(null,
  1006.                                                     "library_cmdobj_queuenext",
  1007.                                                     this.m_cmd_QueueNext);
  1008.  
  1009.       this.m_defaultCommands.appendPlaylistCommands(null,
  1010.                                                     "library_cmdobj_queuenast",
  1011.                                                     this.m_cmd_QueueLast);
  1012.  
  1013.       this.m_defaultCommands.setVisibleCallback(plCmd_ShowDefaultInToolbarCheck);
  1014.  
  1015.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_DEFAULT, this.m_defaultCommands);
  1016.  
  1017.  
  1018.       // --------------------------------------------------------------------------
  1019.       // Construct and publish the smart playlists commands
  1020.       // --------------------------------------------------------------------------
  1021.  
  1022.       this.m_cmd_UpdateSmartPlaylist = new PlaylistCommandsBuilder
  1023.                                            ("update-smartplaylist-cmd");
  1024.  
  1025.       this.m_cmd_UpdateSmartPlaylist.appendAction
  1026.                                         (null,
  1027.                                          "smartpl_cmd_update",
  1028.                                          "&command.smartpl.update",
  1029.                                          "&command.tooltip.smartpl.update",
  1030.                                          plCmd_UpdateSmartPlaylist_TriggerCallback);
  1031.  
  1032.       this.m_cmd_UpdateSmartPlaylist.setCommandShortcut
  1033.                                   (null,
  1034.                                    "smartpl_cmd_update",
  1035.                                    "&command.shortcut.key.smartpl.update",
  1036.                                    "&command.shortcut.keycode.smartpl.update",
  1037.                                    "&command.shortcut.modifiers.smartpl.update",
  1038.                                    true);
  1039.  
  1040.      this.m_cmd_UpdateSmartPlaylist.setCommandVisibleCallback(null,
  1041.                                                               "smartpl_cmd_update",
  1042.                                                               plCmd_NOT(plCmd_isLiveUpdateSmartPlaylist));
  1043.  
  1044.       this.m_cmd_EditSmartPlaylist = new PlaylistCommandsBuilder
  1045.                                          ("properties-smartplaylist-cmd");
  1046.  
  1047.       this.m_cmd_EditSmartPlaylist.appendAction
  1048.                                         (null,
  1049.                                          "smartpl_cmd_properties",
  1050.                                          "&command.smartpl.properties",
  1051.                                          "&command.tooltip.smartpl.properties",
  1052.                                          plCmd_EditSmartPlaylist_TriggerCallback);
  1053.  
  1054.       this.m_cmd_EditSmartPlaylist.setCommandShortcut
  1055.                                   (null,
  1056.                                    "smartpl_cmd_properties",
  1057.                                    "&command.shortcut.key.smartpl.properties",
  1058.                                    "&command.shortcut.keycode.smartpl.properties",
  1059.                                    "&command.shortcut.modifiers.smartpl.properties",
  1060.                                    true);
  1061.  
  1062.       this.m_cmd_EditSmartPlaylist.setCommandVisibleCallback(null,
  1063.                                                              "smartpl_cmd_properties",
  1064.                                                              plCmd_CanModifyPlaylist);
  1065.  
  1066.       this.m_smartPlaylistsCommands = new PlaylistCommandsBuilder
  1067.                                           ("smartplaylist_cmds");
  1068.  
  1069.       this.m_smartPlaylistsCommands.appendPlaylistCommands(null,
  1070.                                                            "library_cmdobj_defaults",
  1071.                                                            this.m_defaultCommands);
  1072.  
  1073.       this.m_cmd_SmartPlaylistSep = new PlaylistCommandsBuilder
  1074.                                         ("separator-smartplaylist-cmd");
  1075.  
  1076.       this.m_cmd_SmartPlaylistSep.appendSeparator(null, "smartpl_separator");
  1077.  
  1078.       this.m_cmd_SmartPlaylistSep.setVisibleCallback(plCmd_NOT(plCmd_ShowForToolbarCheck));
  1079.  
  1080.       this.m_smartPlaylistsCommands.appendPlaylistCommands(null,
  1081.                                                            "smartpl_cmdobj_sep",
  1082.                                                            this.m_cmd_SmartPlaylistSep);
  1083.  
  1084.       this.m_smartPlaylistsCommands.appendPlaylistCommands(null,
  1085.                                                            "smartpl_cmdobj_update",
  1086.                                                            this.m_cmd_UpdateSmartPlaylist);
  1087.  
  1088.       this.m_smartPlaylistsCommands.appendPlaylistCommands(null,
  1089.                                                            "smartpl_cmdobj_properties",
  1090.                                                            this.m_cmd_EditSmartPlaylist);
  1091.  
  1092.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_UPDATESMARTMEDIALIST, this.m_cmd_UpdateSmartPlaylist);
  1093.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_EDITSMARTMEDIALIST, this.m_cmd_EditSmartPlaylist);
  1094.  
  1095.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_SMARTPLAYLIST, this.m_smartPlaylistsCommands);
  1096.       this.m_mgr.registerPlaylistCommandsMediaItem("", "smart", this.m_smartPlaylistsCommands);
  1097.  
  1098.       // --------------------------------------------------------------------------
  1099.       // Construct and publish the web playlist commands
  1100.       // --------------------------------------------------------------------------
  1101.  
  1102.       this.m_webPlaylistCommands = new PlaylistCommandsBuilder
  1103.                                        ("webplaylist-cmds");
  1104.  
  1105.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1106.                                                         "library_cmdobj_play",
  1107.                                                         this.m_cmd_Play);
  1108.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1109.                                                         "library_cmdobj_pause",
  1110.                                                         this.m_cmd_Pause);
  1111.  
  1112.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1113.                                                         "library_cmdobj_remove",
  1114.                                                         this.m_cmd_Remove);
  1115.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1116.                                                         "library_cmdobj_download",
  1117.                                                         this.m_cmd_Download);
  1118.  
  1119.  
  1120.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1121.                                                         "library_cmdobj_addtoplaylist",
  1122.                                                         SBPlaylistCommand_DownloadToPlaylist);
  1123.  
  1124.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1125.                                                         "library_cmdobj_copylocation",
  1126.                                                         this.m_cmd_CopyTrackLocation);
  1127.       this.m_webPlaylistCommands.appendSeparator(null, "separator");
  1128.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1129.                                                         "library_cmdobj_showdlplaylist",
  1130.                                                         this.m_cmd_ShowDownloadPlaylist);
  1131.       this.m_webPlaylistCommands.appendSeparator(null, "web_commands_separator_2");
  1132.  
  1133.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1134.                                                         "library_cmdobj_queuenext",
  1135.                                                         this.m_cmd_QueueNext);
  1136.  
  1137.       this.m_webPlaylistCommands.appendPlaylistCommands(null,
  1138.                                                         "library_cmdobj_queuelast",
  1139.                                                         this.m_cmd_QueueLast);
  1140.  
  1141.       this.m_webPlaylistCommands.setVisibleCallback(plCmd_ShowDefaultInToolbarCheck);
  1142.  
  1143.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_WEBPLAYLIST, this.m_webPlaylistCommands);
  1144.  
  1145.       // Register these commands to the web playlist
  1146.  
  1147.       var webListGUID =
  1148.         prefs.getComplexValue("songbird.library.web",
  1149.                               Ci.nsISupportsString);
  1150.  
  1151.       this.m_mgr.registerPlaylistCommandsMediaItem(webListGUID, "", this.m_webPlaylistCommands);
  1152.  
  1153.       // --------------------------------------------------------------------------
  1154.       // Construct and publish the web media history toolbar commands
  1155.       // --------------------------------------------------------------------------
  1156.  
  1157.       this.m_webMediaHistoryToolbarCommands = new PlaylistCommandsBuilder
  1158.                                                   ("webhistory-cmds");
  1159.  
  1160.       this.m_webMediaHistoryToolbarCommands.appendPlaylistCommands
  1161.                                               (null,
  1162.                                                "library_cmdobj_clearhistory",
  1163.                                                this.m_cmd_ClearHistory);
  1164.  
  1165.       this.m_webMediaHistoryToolbarCommands.setVisibleCallback
  1166.                                                       (plCmd_ShowForToolbarCheck);
  1167.  
  1168.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_WEBTOOLBAR,
  1169.                          this.m_webMediaHistoryToolbarCommands);
  1170.  
  1171.       // Register these commands to the web media history library
  1172.  
  1173.       this.m_mgr.registerPlaylistCommandsMediaItem
  1174.                                                 (webListGUID,
  1175.                                                  "",
  1176.                                                  this.m_webMediaHistoryToolbarCommands);
  1177.       // --------------------------------------------------------------------------
  1178.       // Construct and publish the download playlist commands
  1179.       // --------------------------------------------------------------------------
  1180.  
  1181.       this.m_downloadCommands = new PlaylistCommandsBuilder
  1182.                                     ("download-cmds");
  1183.  
  1184.       this.m_downloadCommands.appendPlaylistCommands(null,
  1185.                                                      "library_cmdobj_play",
  1186.                                                      this.m_cmd_Play);
  1187.       this.m_downloadCommands.appendPlaylistCommands(null,
  1188.                                                      "library_cmdobj_pause",
  1189.                                                      this.m_cmd_Pause);
  1190.       this.m_downloadCommands.appendPlaylistCommands(null,
  1191.                                                      "library_cmdobj_remove",
  1192.                                                      this.m_cmd_Remove);
  1193.       this.m_downloadCommands.appendPlaylistCommands(null,
  1194.                                                      "library_cmdobj_pauseresumedownload",
  1195.                                                      this.m_cmd_PauseResumeDownload);
  1196.  
  1197.       this.m_downloadCommands.setVisibleCallback(plCmd_HideForToolbarCheck);
  1198.  
  1199.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_DOWNLOADPLAYLIST, this.m_downloadCommands);
  1200.  
  1201.       // Get the download device
  1202.       getDownloadDevice();
  1203.  
  1204.       // Register these commands to the download playlist
  1205.  
  1206.       this.m_mgr.registerPlaylistCommandsMediaItem(this.m_downloadListGuid, "", this.m_downloadCommands);
  1207.  
  1208.       // --------------------------------------------------------------------------
  1209.       // Construct and publish the device library commands
  1210.       // --------------------------------------------------------------------------
  1211.  
  1212.       this.m_deviceLibraryCommands = new PlaylistCommandsBuilder
  1213.                                          ("device-cmds");
  1214.  
  1215.       this.m_deviceLibraryCommands.appendPlaylistCommands(null,
  1216.                                                     "library_cmdobj_edit",
  1217.                                                     this.m_cmd_Edit);
  1218.       this.m_deviceLibraryCommands.appendPlaylistCommands(null,
  1219.                                                     "library_cmdobj_reveal",
  1220.                                                     this.m_cmd_Reveal);
  1221.  
  1222.       this.m_deviceLibraryCommands.appendSeparator(null, "default_commands_separator_1");
  1223.  
  1224.       this.m_deviceLibraryCommands.appendPlaylistCommands(null,
  1225.                                                     "library_cmdobj_addtolibrary",
  1226.                                                     SBPlaylistCommand_AddToLibrary);
  1227.  
  1228.       this.m_deviceLibraryCommands.appendSeparator(null, "default_commands_separator_2");
  1229.  
  1230.       this.m_deviceLibraryCommands.appendPlaylistCommands(null,
  1231.                                                     "library_cmdobj_remove",
  1232.                                                     this.m_cmd_Remove);
  1233.  
  1234.       this.m_deviceLibraryCommands.setVisibleCallback(plCmd_ShowDefaultInToolbarCheck);
  1235.  
  1236.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_DEVICE_LIBRARY_CONTEXTMENU,
  1237.                          this.m_deviceLibraryCommands);
  1238.  
  1239.       // --------------------------------------------------------------------------
  1240.       // Construct and publish the cd device library commands
  1241.       // --------------------------------------------------------------------------
  1242.  
  1243.       this.m_cdDeviceLibraryCommands = new PlaylistCommandsBuilder
  1244.                                            ("cddevice-cmds");
  1245.  
  1246.       this.m_cdDeviceLibraryCommands.appendPlaylistCommands(null,
  1247.                                                     "library_cmdobj_check",
  1248.                                                     this.m_cmd_CheckAll);
  1249.  
  1250.       this.m_cdDeviceLibraryCommands.appendPlaylistCommands(null,
  1251.                                                     "library_cmdobj_uncheck",
  1252.                                                     this.m_cmd_UncheckAll);
  1253.  
  1254.       this.m_cdDeviceLibraryCommands.appendPlaylistCommands(null,
  1255.                                                     "library_cmdobj_edit",
  1256.                                                     this.m_cmd_Edit);
  1257.  
  1258.       this.m_cdDeviceLibraryCommands.appendPlaylistCommands(null,
  1259.                                                     "library_cmdobj_lookup",
  1260.                                                     this.m_cmd_LookupCDInfo);
  1261.  
  1262.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_CDDEVICE_LIBRARY,
  1263.                          this.m_cdDeviceLibraryCommands);
  1264.  
  1265.       // --------------------------------------------------------------------------
  1266.       // Construct and publish the play queue library commands
  1267.       // --------------------------------------------------------------------------
  1268.  
  1269.       this.m_playQueueLibraryCommands = new PlaylistCommandsBuilder
  1270.                                             ("playqueue-toolbar-cmds");
  1271.  
  1272.       this.m_playQueueLibraryCommands.appendPlaylistCommands(null,
  1273.                                                     "playqueue_cmdobj_savetoplaylist",
  1274.                                                     this.m_cmd_playqueue_SaveToPlaylist);
  1275.  
  1276.       this.m_playQueueLibraryCommands.appendPlaylistCommands(null,
  1277.                                                     "playqueue_cmdobj_clearall",
  1278.                                                     this.m_cmd_playqueue_ClearAll);
  1279.  
  1280.       this.m_playQueueLibraryCommands.appendPlaylistCommands(null,
  1281.                                                     "playqueue_cmdobj_clearhistory",
  1282.                                                     this.m_cmd_playqueue_ClearHistory);
  1283.  
  1284.       this.m_playQueueLibraryCommands.setVisibleCallback(plCmd_ShowForToolbarCheck);
  1285.  
  1286.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_PLAYQUEUE_LIBRARY,
  1287.                          this.m_playQueueLibraryCommands);
  1288.  
  1289.       // get the GUID for the play queue's media list
  1290.       var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  1291.                            .getService(Ci.sbIPlayQueueService);
  1292.       var playQueueListGUID = queueService.mediaList.guid;
  1293.  
  1294.       this.m_mgr.registerPlaylistCommandsMediaItem(playQueueListGUID, "", this.m_playQueueLibraryCommands);
  1295.  
  1296.       // --------------------------------------------------------------------------
  1297.       // Construct and publish the play queue commands
  1298.       // --------------------------------------------------------------------------
  1299.  
  1300.       this.m_playQueueCommands = new PlaylistCommandsBuilder
  1301.                                      ("playqueue-menu-cmds");
  1302.  
  1303.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1304.                                                     "library_cmdobj_play",
  1305.                                                     this.m_cmd_Play);
  1306.  
  1307.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1308.                                                     "library_cmdobj_pause",
  1309.                                                     this.m_cmd_Pause);
  1310.  
  1311.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1312.                                                     "library_cmdobj_reveal",
  1313.                                                     this.m_cmd_Reveal);
  1314.  
  1315.       this.m_playQueueCommands.appendSeparator(null, "default_commands_separator_1");
  1316.  
  1317.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1318.                                                     "library_cmdobj_addtoplaylist",
  1319.                                                     SBPlaylistCommand_AddToPlaylist);
  1320.  
  1321.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1322.                                                     "library_cmdobj_addtolibrary",
  1323.                                                     SBPlaylistCommand_AddToLibrary);
  1324.  
  1325.       this.m_playQueueCommands.appendSeparator(null, "default_commands_separator_2");
  1326.  
  1327.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1328.                                                     "library_cmdobj_rescan",
  1329.                                                     this.m_cmd_Rescan);
  1330.  
  1331.       this.m_playQueueCommands.appendPlaylistCommands(null,
  1332.                                                     "library_cmdobj_remove",
  1333.                                                     this.m_cmd_Remove);
  1334.  
  1335.       this.m_playQueueCommands.setVisibleCallback(plCmd_HideForToolbarCheck);
  1336.  
  1337.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_PLAYQUEUE, this.m_playQueueCommands);
  1338.  
  1339.       this.m_mgr.registerPlaylistCommandsMediaItem(playQueueListGUID, "", this.m_playQueueCommands);
  1340.  
  1341.       // --------------------------------------------------------------------------
  1342.       // Construct and publish the download toolbar commands
  1343.       // --------------------------------------------------------------------------
  1344.  
  1345.       this.m_downloadToolbarCommands = new PlaylistCommandsBuilder
  1346.                                            ("download-toolbar-cmds");
  1347.  
  1348.       this.m_downloadToolbarCommands.appendPlaylistCommands
  1349.                                               (null,
  1350.                                                "library_cmdobj_cleanupdownloads",
  1351.                                                this.m_cmd_CleanUpDownloads);
  1352.       this.m_downloadToolbarCommands.appendPlaylistCommands
  1353.                                             (null,
  1354.                                              "library_cmdobj_pauseresumedownload",
  1355.                                              this.m_cmd_PauseResumeDownload);
  1356.  
  1357.       this.m_downloadToolbarCommands.setVisibleCallback
  1358.                                                       (plCmd_ShowForToolbarCheck);
  1359.       this.m_downloadToolbarCommands.setInitCallback(plCmd_DownloadInit);
  1360.       this.m_downloadToolbarCommands.setShutdownCallback(plCmd_DownloadShutdown);
  1361.  
  1362.       this.m_mgr.publish(kPlaylistCommands.MEDIAITEM_DOWNLOADTOOLBAR,
  1363.                          this.m_downloadToolbarCommands);
  1364.  
  1365.       // Register these commands to the download playlist
  1366.  
  1367.       this.m_mgr.registerPlaylistCommandsMediaItem
  1368.                                                 (this.m_downloadListGuid,
  1369.                                                  "",
  1370.                                                  this.m_downloadToolbarCommands);
  1371.  
  1372.       // --------------------------------------------------------------------------
  1373.       // Construct and publish the download service tree commands
  1374.       // --------------------------------------------------------------------------
  1375.  
  1376.       this.m_downloadCommandsServicePane = new PlaylistCommandsBuilder
  1377.                                                ("download-servicepane-cmds");
  1378.  
  1379.       this.m_downloadCommandsServicePane.
  1380.         appendPlaylistCommands(null,
  1381.                                "library_cmdobj_pauseresumedownload",
  1382.                                this.m_cmd_PauseResumeDownload);
  1383.  
  1384.       this.m_downloadCommandsServicePane.setInitCallback(plCmd_DownloadInit);
  1385.       this.m_downloadCommandsServicePane.setShutdownCallback(plCmd_DownloadShutdown);
  1386.  
  1387.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_DOWNLOADPLAYLIST, this.m_downloadCommandsServicePane);
  1388.  
  1389.       this.m_mgr.registerPlaylistCommandsMediaList(this.m_downloadListGuid, "", this.m_downloadCommandsServicePane);
  1390.  
  1391.       // --------------------------------------------------------------------------
  1392.       // Construct and publish the service tree playlist commands
  1393.       // --------------------------------------------------------------------------
  1394.  
  1395.       this.m_serviceTreeDefaultCommands = new PlaylistCommandsBuilder
  1396.                                               ("servicetree-cmds");
  1397.  
  1398.       this.m_serviceTreeDefaultCommands.appendPlaylistCommands(null,
  1399.                                               "servicetree_cmdobj_play",
  1400.                                               this.m_cmd_list_Play);
  1401.  
  1402.       this.m_serviceTreeDefaultCommands.appendPlaylistCommands(null,
  1403.                                               "servicetree_cmdobj_remove",
  1404.                                               this.m_cmd_list_Remove);
  1405.  
  1406.       this.m_serviceTreeDefaultCommands.setCommandEnabledCallback(null,
  1407.                                               "servicetree_cmdobj_remove",
  1408.                                               plCmd_CanModifyPlaylist);
  1409.  
  1410.       this.m_serviceTreeDefaultCommands.appendPlaylistCommands(null,
  1411.                                               "servicetree_cmdobj_rename",
  1412.                                               this.m_cmd_list_Rename);
  1413.  
  1414.       this.m_serviceTreeDefaultCommands.setCommandEnabledCallback(null,
  1415.                                               "servicetree_cmdobj_rename",
  1416.                                               plCmd_CanModifyPlaylist);
  1417.  
  1418.       this.m_serviceTreeDefaultCommands.appendPlaylistCommands(null,
  1419.                                               "servicetree_cmdobj_queuenext",
  1420.                                               this.m_cmd_list_QueueNext);
  1421.  
  1422.       this.m_serviceTreeDefaultCommands.appendPlaylistCommands(null,
  1423.                                               "servicetree_cmdobj_queuelast",
  1424.                                               this.m_cmd_list_QueueLast);
  1425.  
  1426.       this.m_mgr.publish(kPlaylistCommands.MEDIALIST_DEFAULT, this.m_serviceTreeDefaultCommands);
  1427.  
  1428.       // Register these commands to simple and smart playlists
  1429.  
  1430.       this.m_mgr.registerPlaylistCommandsMediaList( "", "simple", this.m_serviceTreeDefaultCommands );
  1431.       this.m_mgr.registerPlaylistCommandsMediaList( "", "smart",  this.m_serviceTreeDefaultCommands );
  1432.     } catch (e) {
  1433.       Cu.reportError(e);
  1434.     }
  1435.  
  1436.     // notify observers that the default commands are now ready
  1437.     var observerService = Cc["@mozilla.org/observer-service;1"]
  1438.                             .getService(Ci.nsIObserverService);
  1439.     observerService.notifyObservers(null, "playlist-commands-ready", "default");
  1440.   },
  1441.  
  1442.   // ==========================================================================
  1443.   // SHUTDOWN
  1444.   // ==========================================================================
  1445.   shutdownCommands: function() {
  1446.     // notify observers that the default commands are going away
  1447.     var observerService = Cc["@mozilla.org/observer-service;1"]
  1448.                             .getService(Ci.nsIObserverService);
  1449.     observerService.notifyObservers(null, "playlist-commands-shutdown", "default");
  1450.  
  1451.     var prefs = Cc["@mozilla.org/preferences-service;1"]
  1452.                   .getService(Ci.nsIPrefBranch2);
  1453.  
  1454.     // Un-publish atomic commands
  1455.  
  1456.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_PLAY, this.m_cmd_Play);
  1457.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_PAUSE, this.m_cmd_Pause);
  1458.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_REMOVE, this.m_cmd_Remove);
  1459.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_EDIT, this.m_cmd_Edit);
  1460.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_DOWNLOAD, this.m_cmd_Download);
  1461.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_RESCAN, this.m_cmd_Rescan);
  1462.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_REVEAL, this.m_cmd_Reveal);
  1463.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_ADDTOPLAYLIST, SBPlaylistCommand_AddToPlaylist);
  1464.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_ADDTODEVICE, SBPlaylistCommand_AddToDevice);
  1465.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_ADDTOLIBRARY, SBPlaylistCommand_AddToLibrary);
  1466.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_COPYTRACKLOCATION, this.m_cmd_CopyTrackLocation);
  1467.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_SHOWDOWNLOADPLAYLIST, this.m_cmd_ShowDownloadPlaylist);
  1468.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_PAUSERESUMEDOWNLOAD, this.m_cmd_PauseResumeDownload);
  1469.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_CLEANUPDOWNLOADS, this.m_cmd_CleanUpDownloads);
  1470.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_CLEARHISTORY, this.m_cmd_ClearHistory);
  1471.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_GETARTWORK, this.m_cmd_GetArtwork);
  1472.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_QUEUENEXT, this.m_cmd_QueueNext);
  1473.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_QUEUELAST, this.m_cmd_QueueLast);
  1474.  
  1475.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_PLAY, this.m_cmd_list_Play);
  1476.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_REMOVE, this.m_cmd_list_Remove);
  1477.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_RENAME, this.m_cmd_list_Rename);
  1478.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_QUEUENEXT, this.m_cmd_list_QueueNext);
  1479.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_QUEUELAST, this.m_cmd_list_QueueLast);
  1480.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_UPDATESMARTMEDIALIST, this.m_cmd_UpdateSmartPlaylist);
  1481.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_EDITSMARTMEDIALIST, this.m_cmd_EditSmartPlaylist);
  1482.  
  1483.     // Un-publish bundled commands
  1484.  
  1485.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_DEFAULT, this.m_defaultCommands);
  1486.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_WEBPLAYLIST, this.m_webPlaylistCommands);
  1487.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_WEBTOOLBAR, this.m_webMediaHistoryToolbarCommands);
  1488.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_DOWNLOADPLAYLIST, this.m_downloadCommands);
  1489.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_DOWNLOADTOOLBAR, this.m_downloadToolbarCommands);
  1490.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_DEFAULT, this.m_serviceTreeDefaultCommands);
  1491.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_DOWNLOADPLAYLIST, this.m_downloadCommandsServicePane);
  1492.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_SMARTPLAYLIST, this.m_smartPlaylistsCommands);
  1493.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_DEVICE_LIBRARY_CONTEXTMENU, this.m_deviceLibraryCommands);
  1494.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_DEVICE_LIBRARY_TOOLBAR, this.m_cmd_DeviceToolbarCmds);
  1495.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_CDDEVICE_LIBRARY, this.m_cdDeviceLibraryCommands);
  1496.     this.m_mgr.withdraw(kPlaylistCommands.MEDIAITEM_PLAYQUEUE, this.m_playQueueCommands);
  1497.     this.m_mgr.withdraw(kPlaylistCommands.MEDIALIST_PLAYQUEUE_LIBRARY, this.m_playQueueLibraryCommands);
  1498.  
  1499.     // Un-register download playlist commands
  1500.  
  1501.     this.m_mgr.unregisterPlaylistCommandsMediaItem(this.m_downloadListGuid,
  1502.                                                    "",
  1503.                                                    this.m_downloadCommands);
  1504.  
  1505.     this.m_mgr.unregisterPlaylistCommandsMediaItem
  1506.                                               (this.m_downloadListGuid,
  1507.                                                "",
  1508.                                                this.m_downloadToolbarCommands);
  1509.  
  1510.     this.m_mgr.unregisterPlaylistCommandsMediaList
  1511.                                               (this.m_downloadListGuid,
  1512.                                                "",
  1513.                                                this.m_downloadCommandsServicePane);
  1514.  
  1515.     g_downloadDevice = null;
  1516.  
  1517.     g_webLibrary = null;
  1518.  
  1519.     // Un-register web playlist commands
  1520.  
  1521.     var webListGUID =
  1522.       prefs.getComplexValue("songbird.library.web",
  1523.                             Ci.nsISupportsString);
  1524.  
  1525.     this.m_mgr.unregisterPlaylistCommandsMediaItem(webListGUID,
  1526.                                                    "",
  1527.                                                    this.m_webPlaylistCommands);
  1528.  
  1529.     // Un-register web media history commands
  1530.  
  1531.     this.m_mgr.
  1532.       unregisterPlaylistCommandsMediaItem(webListGUID,
  1533.                                           "",
  1534.                                           this.m_webMediaHistoryToolbarCommands);
  1535.  
  1536.     // Un-register the playqueue commands
  1537.     var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  1538.                          .getService(Ci.sbIPlayQueueService);
  1539.     var playQueueListGUID = queueService.mediaList.guid;
  1540.  
  1541.     this.m_mgr.
  1542.       unregisterPlaylistCommandsMediaItem(playQueueListGUID,
  1543.                                           "",
  1544.                                           this.m_playQueueCommands);
  1545.  
  1546.     this.m_mgr.
  1547.       unregisterPlaylistCommandsMediaItem(playQueueListGUID,
  1548.                                           "",
  1549.                                           this.m_playQueueLibraryCommands);
  1550.  
  1551.  
  1552.     // Un-register smart playlist commands
  1553.  
  1554.     this.m_mgr.
  1555.       unregisterPlaylistCommandsMediaItem("",
  1556.                                           "smart",
  1557.                                           this.m_smartPlaylistsCommands);
  1558.  
  1559.  
  1560.     // Un-register servicetree commands
  1561.  
  1562.     this.m_mgr.
  1563.       unregisterPlaylistCommandsMediaList("",
  1564.                                           "simple",
  1565.                                           this.m_serviceTreeDefaultCommands);
  1566.     this.m_mgr.
  1567.       unregisterPlaylistCommandsMediaList("",
  1568.                                           "smart",
  1569.                                           this.m_serviceTreeDefaultCommands);
  1570.  
  1571.     // Shutdown all command objects, this ensures that no external reference
  1572.     // remains in their internal arrays. The AddTo helpers may or may not be
  1573.     // active depending on which set of playlist commands is actually used,
  1574.     // but their shutdownCommands methods are no-ops if the commands do not
  1575.     // exist.
  1576.     SBPlaylistCommand_AddToPlaylist.shutdownCommands();
  1577.     SBPlaylistCommand_AddToDevice.shutdownCommands();
  1578.     SBPlaylistCommand_AddToLibrary.shutdownCommands();
  1579.     this.m_cmd_Play.shutdown();
  1580.     this.m_cmd_Pause.shutdown();
  1581.     this.m_cmd_Remove.shutdown();
  1582.     this.m_cmd_Edit.shutdown();
  1583.     this.m_cmd_Download.shutdown();
  1584.     this.m_cmd_Rescan.shutdown();
  1585.     this.m_cmd_Reveal.shutdown();
  1586.     this.m_cmd_CopyTrackLocation.shutdown();
  1587.     this.m_cmd_ShowDownloadPlaylist.shutdown();
  1588.     this.m_cmd_PauseResumeDownload.shutdown();
  1589.     this.m_cmd_CleanUpDownloads.shutdown();
  1590.     this.m_cmd_ClearHistory.shutdown();
  1591.     this.m_cmd_GetArtwork.shutdown();
  1592.     this.m_cmd_QueueNext.shutdown();
  1593.     this.m_cmd_QueueLast.shutdown();
  1594.     this.m_cmd_list_Play.shutdown();
  1595.     this.m_cmd_list_Remove.shutdown();
  1596.     this.m_cmd_list_Rename.shutdown();
  1597.     this.m_cmd_list_QueueNext.shutdown();
  1598.     this.m_cmd_list_QueueLast.shutdown();
  1599.     this.m_cmd_UpdateSmartPlaylist.shutdown();
  1600.     this.m_cmd_EditSmartPlaylist.shutdown();
  1601.     this.m_cmd_SmartPlaylistSep.shutdown();
  1602.     this.m_defaultCommands.shutdown();
  1603.     this.m_webPlaylistCommands.shutdown();
  1604.     this.m_webMediaHistoryToolbarCommands.shutdown();
  1605.     this.m_smartPlaylistsCommands.shutdown();
  1606.     this.m_downloadCommands.shutdown();
  1607.     this.m_downloadToolbarCommands.shutdown();
  1608.     this.m_downloadCommandsServicePane.shutdown();
  1609.     this.m_serviceTreeDefaultCommands.shutdown();
  1610.     this.m_deviceLibraryCommands.shutdown();
  1611.     this.m_cmd_ShowOnlyOnDevice.shutdown();
  1612.     this.m_cmd_ShowAllOnDevice.shutdown();
  1613.     this.m_cmd_DeviceToolbarCmds.shutdown();
  1614.     this.m_cdDeviceLibraryCommands.shutdown();
  1615.     this.m_cmd_playqueue_SaveToPlaylist.shutdown();
  1616.     this.m_cmd_playqueue_ClearAll.shutdown();
  1617.     this.m_cmd_playqueue_ClearHistory.shutdown();
  1618.     this.m_playQueueCommands.shutdown();
  1619.     this.m_playQueueLibraryCommands.shutdown();
  1620.     this.m_cmd_LookupCDInfo.shutdown();
  1621.     this.m_cmd_CheckAll.shutdown();
  1622.     this.m_cmd_UncheckAll.shutdown();
  1623.  
  1624.     g_dataRemoteService = null;
  1625.  
  1626.     var obs = Cc["@mozilla.org/observer-service;1"]
  1627.                 .getService(Ci.nsIObserverService);
  1628.  
  1629.     obs.removeObserver(this, "quit-application");
  1630.   },
  1631.  
  1632.   // nsIObserver
  1633.   observe: function(aSubject, aTopic, aData) {
  1634.     switch (aTopic) {
  1635.       case "final-ui-startup":
  1636.         this.initCommands();
  1637.         break;
  1638.       case "quit-application":
  1639.         this.shutdownCommands();
  1640.         break;
  1641.     }
  1642.   },
  1643.  
  1644.   QueryInterface:
  1645.     XPCOMUtils.generateQI([Ci.nsIObserver])
  1646. };
  1647.  
  1648. function unwrap(obj) {
  1649.   if (obj && obj.wrappedJSObject)
  1650.     obj = obj.wrappedJSObject;
  1651.   return obj;
  1652. }
  1653.  
  1654. // --------------------------------------------------------------------------
  1655. // Called when the play action is triggered
  1656. function plCmd_Play_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1657.   var playbackControl = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
  1658.                           .getService(Ci.sbIMediacoreManager).playbackControl;
  1659.   var view = unwrap(aContext.playlist).mediaListView;
  1660.  
  1661.   /* if the current selection is in the sequencer, but not actively playing
  1662.    * have the sequencer resume playback */
  1663.   if (isCurrentSelectionActive(view)) {
  1664.     playbackControl.play();
  1665.   }
  1666.   else if (plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  1667.     /* if something is selected but it is not active at the moment,
  1668.      * begin playing it */
  1669.     unwrap(aContext.playlist).sendPlayEvent();
  1670.   }
  1671. }
  1672.  
  1673. // Called to determine if the Play playlist command should be visible
  1674. function plCmd_Play_VisibleCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1675.   var view = unwrap(aContext.playlist).mediaListView
  1676.  
  1677.   // we don't show play when more than 1 item is selected
  1678.   if (view.selection.count > 1)
  1679.   {
  1680.     return false;
  1681.   }
  1682.  
  1683.   var mediaCoreMgr = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
  1684.                     .getService(Ci.sbIMediacoreManager);
  1685.  
  1686.   /* we show the play command as long as we are not currently playing the
  1687.    * selected track*/
  1688.   return !(mediaCoreMgr.status.state == Ci.sbIMediacoreStatus.STATUS_PLAYING &&
  1689.            isCurrentSelectionActive(view))
  1690. }
  1691.  
  1692. /* Returns true if the currently selected track is active in the sequencer.
  1693.  * This does not mean the track is necessarily playing as it could be paused */
  1694. function isCurrentSelectionActive(mediaListView) {
  1695.   var mediaCoreMgr = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
  1696.                        .getService(Ci.sbIMediacoreManager);
  1697.  
  1698.   var sequencer = mediaCoreMgr.sequencer;
  1699.   var currItem = mediaListView.selection.currentMediaItem;
  1700.   var currMediaList = mediaListView.mediaList;
  1701.  
  1702.   // if the sequencer's active item is the selected item, return true
  1703.   return (currItem.equals(sequencer.currentItem) &&
  1704.           currMediaList.equals(sequencer.view.mediaList) &&
  1705.           mediaListView.selection.currentIndex == sequencer.viewPosition);
  1706. }
  1707.  
  1708. // Called when the pause action is triggered
  1709. function plCmd_Pause_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1710.   var playbackControl = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
  1711.                        .getService(Ci.sbIMediacoreManager).playbackControl;
  1712.   playbackControl.pause();
  1713. }
  1714.  
  1715. // Called to determine if the Pause playlist command should be visible
  1716. function plCmd_Pause_VisibleCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1717.   var selection = unwrap(aContext.playlist).mediaListView.selection;
  1718.  
  1719.   // we don't show pause when more than 1 item is selected
  1720.   if (selection.count > 1)
  1721.   {
  1722.     return false;
  1723.   }
  1724.  
  1725.   var mediaCoreMgr = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
  1726.                        .getService(Ci.sbIMediacoreManager);
  1727.  
  1728.   // figure out if the play command is currently visible
  1729.   var isPlayVisible =
  1730.       plCmd_Play_VisibleCallback(aContext, aSubMenuId, aCommandId, aHost);
  1731.  
  1732.   /* we only show the pause command if we are currently playing and we are not
  1733.    * currently showing the play command */
  1734.   return (!isPlayVisible &&
  1735.           mediaCoreMgr.status.state == Ci.sbIMediacoreStatus.STATUS_PLAYING);
  1736. }
  1737.  
  1738. // Called when the edit action is triggered
  1739. function plCmd_Edit_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1740.   if (plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  1741.     var playlist = unwrap(aContext.playlist);
  1742.     playlist.onPlaylistEditor();
  1743.   }
  1744. }
  1745.  
  1746. // Called when the remove action is triggered
  1747. function plCmd_Remove_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1748.   // remove the selected tracks, if any
  1749.   if (plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  1750.     unwrap(aContext.playlist).removeSelectedTracks();
  1751.   }
  1752. }
  1753.  
  1754. // Called when the download action is triggered
  1755. function plCmd_Download_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1756.   try
  1757.   {
  1758.     var playlist = unwrap(aContext.playlist);
  1759.     var window = unwrap(aContext.window);
  1760.     if(playlist.mediaListView.selection.count) {
  1761.       onBrowserTransfer(new SelectionUnwrapper(
  1762.                        playlist.mediaListView.selection.selectedIndexedMediaItems));
  1763.     }
  1764.     else {
  1765.       var allItems = {
  1766.         items: [],
  1767.         onEnumerationBegin: function(aMediaList) {
  1768.         },
  1769.         onEnumeratedItem: function(aMediaList, aMediaItem) {
  1770.           this.items.push(aMediaItem);
  1771.         },
  1772.         onEnumerationEnd: function(aMediaList, aResultCode) {
  1773.         }
  1774.       };
  1775.  
  1776.       playlist.mediaList.enumerateAllItems(allItems);
  1777.  
  1778.       var itemEnum = ArrayConverter.enumerator(allItems.items);
  1779.       onBrowserTransfer(itemEnum);
  1780.     }
  1781.   }
  1782.   catch( err )
  1783.   {
  1784.     Cu.reportError(err);
  1785.   }
  1786. }
  1787.  
  1788. function plCmd_Rescan_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1789.   try
  1790.   {
  1791.     var playlist = unwrap(aContext.playlist);
  1792.     var window = unwrap(aContext.window);
  1793.  
  1794.     if(playlist.mediaListView.selection.count) {
  1795.       var mediaItemArray = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
  1796.                              .createInstance(Ci.nsIMutableArray);
  1797.  
  1798.       var selection = playlist.mediaListView.selection.selectedIndexedMediaItems;
  1799.       while(selection.hasMoreElements()) {
  1800.         let item = selection.getNext()
  1801.                             .QueryInterface(Ci.sbIIndexedMediaItem).mediaItem;
  1802.         mediaItemArray.appendElement(item, false);
  1803.       }
  1804.  
  1805.       var metadataService = Cc["@songbirdnest.com/Songbird/FileMetadataService;1"]
  1806.                               .getService(Ci.sbIFileMetadataService);
  1807.       var job = metadataService.read(mediaItemArray);
  1808.       SBJobUtils.showProgressDialog(job, null);
  1809.     }
  1810.   }
  1811.   catch( err )
  1812.   {
  1813.     Cu.reportError(err);
  1814.   }
  1815. }
  1816.  
  1817. function plCmd_Reveal_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1818.   try
  1819.   {
  1820.     var playlist = unwrap(aContext.playlist);
  1821.     var window = unwrap(aContext.window);
  1822.  
  1823.     if (playlist.mediaListView.selection.count != 1) { return; }
  1824.  
  1825.     var selection = playlist.mediaListView.selection.selectedIndexedMediaItems;
  1826.     var item = selection.getNext().QueryInterface(Ci.sbIIndexedMediaItem).mediaItem;
  1827.     if (!item) {
  1828.       Cu.reportError("No item selected in reveal playlist command.")
  1829.     }
  1830.  
  1831.     var uri = item.contentSrc;
  1832.     if (!uri || uri.scheme != "file") { return; }
  1833.  
  1834.     let f = uri.QueryInterface(Ci.nsIFileURL).file;
  1835.     try {
  1836.       // Show the directory containing the file and select the file
  1837.       f.QueryInterface(Ci.nsILocalFile);
  1838.       f.reveal();
  1839.     } catch (e) {
  1840.       // If reveal fails for some reason (e.g., it's not implemented on unix or
  1841.       // the file doesn't exist), try using the parent if we have it.
  1842.       let parent = f.parent.QueryInterface(Ci.nsILocalFile);
  1843.       if (!parent)
  1844.         return;
  1845.  
  1846.       try {
  1847.         // "Double click" the parent directory to show where the file should be
  1848.         parent.launch();
  1849.       } catch (e) {
  1850.         // If launch also fails (probably because it's not implemented), let the
  1851.         // OS handler try to open the parent
  1852.         var parentUri = Cc["@mozilla.org/network/io-service;1"]
  1853.                           .getService(Ci.nsIIOService).newFileURI(parent);
  1854.  
  1855.         var protocolSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
  1856.                             .getService(Ci.nsIExternalProtocolService);
  1857.         protocolSvc.loadURI(parentUri);
  1858.       }
  1859.     }
  1860.   }
  1861.   catch( err )
  1862.   {
  1863.     Cu.reportError(err);
  1864.   }
  1865. }
  1866.  
  1867. // Called when the "copy track location" action is triggered
  1868. function plCmd_CopyTrackLocation_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1869.   var clipboardtext = "";
  1870.   var urlCol = "url";
  1871.   var playlist = unwrap(aContext.playlist);
  1872.  
  1873.   var selectedEnum = playlist.mediaListView.selection.selectedIndexedMediaItems;
  1874.   while (selectedEnum.hasMoreElements()) {
  1875.     var curItem = selectedEnum.getNext();
  1876.     if (curItem) {
  1877.       var originURL = curItem.mediaItem.getProperty(SBProperties.contentURL);
  1878.       if (clipboardtext != "")
  1879.         clipboardtext += "\n";
  1880.       clipboardtext += originURL;
  1881.     }
  1882.   }
  1883.  
  1884.   var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
  1885.                     .getService(Ci.nsIClipboardHelper);
  1886.   clipboard.copyString(clipboardtext);
  1887. }
  1888.  
  1889. // Called whne the "show download playlist" action is triggered
  1890. function plCmd_ShowDownloadPlaylist_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1891.   var window = unwrap(aContext.window);
  1892.   var browser = window.gBrowser;
  1893.   if (browser) {
  1894.     var device = getDownloadDevice();
  1895.     if (device) {
  1896.       browser.loadMediaList(device.downloadMediaList);
  1897.     }
  1898.   }
  1899. }
  1900.  
  1901. // Called when the pause/resume download action is triggered
  1902. function plCmd_PauseResumeDownload_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1903.   var device = getDownloadDevice();
  1904.   if (!device) return;
  1905.   var deviceState = device.getDeviceState('');
  1906.   if ( deviceState == Ci.sbIDeviceBase.STATE_DOWNLOADING )
  1907.   {
  1908.     device.suspendTransfer('');
  1909.   }
  1910.   else if ( deviceState == Ci.sbIDeviceBase.STATE_DOWNLOAD_PAUSED )
  1911.   {
  1912.     device.resumeTransfer('');
  1913.   }
  1914.   // Command buttons will update when device sends notification
  1915. }
  1916.  
  1917. // Called when the clean up downloads action is triggered
  1918. function plCmd_CleanUpDownloads_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1919.   var device = getDownloadDevice();
  1920.   if (!device) return;
  1921.  
  1922.   device.clearCompletedItems();
  1923.  
  1924.   // Command buttons will update when device sends notification
  1925. }
  1926.  
  1927. // Called when the clear history action is triggered
  1928. function plCmd_ClearHistory_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1929.   var wl = getWebLibrary();
  1930.   if (wl) {
  1931.     wl.clear();
  1932.   }
  1933. }
  1934.  
  1935. // Called when the get album artwork action is triggered
  1936. function plCmd_GetArtwork_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1937.   // Load up a fetcher set, create a list and start the fetch
  1938.   if (plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  1939.     var playlist = unwrap(aContext.playlist);
  1940.  
  1941.     // Only look up artwork for audio items.
  1942.     var isAudioItem = function(aElement) {
  1943.       return aElement.getProperty(SBProperties.contentType) == "audio";
  1944.     };
  1945.     var selectedAudioItems = new SBFilteredEnumerator(
  1946.         playlist.mediaListView.selection.selectedMediaItems,
  1947.         isAudioItem);
  1948.  
  1949.     // We need to convert our JS object into an XPCOM object.
  1950.     // Mook claims this is actually the best way to do this.
  1951.     var sip = Cc["@mozilla.org/supports-interface-pointer;1"]
  1952.                     .createInstance(Ci.nsISupportsInterfacePointer);
  1953.     sip.data = selectedAudioItems;
  1954.     selectedAudioItems = sip.data;
  1955.  
  1956.     sbCoverHelper.getArtworkForItems(selectedAudioItems,
  1957.                                      null,
  1958.                                      playlist.library);
  1959.   }
  1960. }
  1961.  
  1962. // Called when the queueNext action is triggered
  1963. function plCmd_QueueNext_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1964.   var wrapper =
  1965.       plCmd_GetSelectedItemWrapperForPlaylist(unwrap(aContext.playlist));
  1966.   if (wrapper) {
  1967.     let queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  1968.                        .getService(Ci.sbIPlayQueueService);
  1969.     queueService.queueSomeNext(wrapper);
  1970.   }
  1971. }
  1972.  
  1973. // Called when the queueLast action is triggered
  1974. function plCmd_QueueLast_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  1975.   var wrapper =
  1976.       plCmd_GetSelectedItemWrapperForPlaylist(unwrap(aContext.playlist));
  1977.   if (wrapper) {
  1978.     let queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  1979.                          .getService(Ci.sbIPlayQueueService);
  1980.     queueService.queueSomeLast(wrapper);
  1981.   }
  1982. }
  1983.  
  1984. // Helper function to get a wrapped enumerator of the selected items in a
  1985. // mediaList. Returns null if nothing is selected.
  1986. function plCmd_GetSelectedItemWrapperForPlaylist(aPlaylist) {
  1987.   var wrapper = null;
  1988.   if (aPlaylist.mediaListView.selection.count) {
  1989.     let indexedSelection =
  1990.       aPlaylist.mediaListView.selection.selectedIndexedMediaItems;
  1991.     wrapper = Cc["@songbirdnest.com/Songbird/Library/EnumeratorWrapper;1"]
  1992.                 .createInstance(Ci.sbIMediaListEnumeratorWrapper);
  1993.     wrapper.initialize(indexedSelection);
  1994.   }
  1995.  
  1996.   return wrapper;
  1997. }
  1998.  
  1999. // Called when the save to playlist action is triggered
  2000. function plCmd_QueueSaveToPlaylist_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2001.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2002.                        .getService(Ci.sbIPlayQueueService);
  2003.   var newMediaList = aContext.window.makeNewPlaylist("simple");
  2004.   newMediaList.addAll(queueService.mediaList);
  2005. }
  2006.  
  2007. // Called when the clear all action is triggered
  2008. function plCmd_QueueClearAll_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2009.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2010.                        .getService(Ci.sbIPlayQueueService);
  2011.   queueService.clearAll();
  2012. }
  2013.  
  2014. // Called when the clear history playlist action is triggered
  2015. function plCmd_QueueClearHistory_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2016.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2017.                        .getService(Ci.sbIPlayQueueService);
  2018.   queueService.clearHistory();
  2019. }
  2020.  
  2021. // Called when the lookup cd info action is triggered
  2022. function plCmd_LookupCDInfo_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2023.   var firstItem;
  2024.   try {
  2025.     var playlist = unwrap(aContext.playlist);
  2026.     var medialist = playlist.mediaListView.mediaList;
  2027.     var firstItem = medialist.getItemByIndex(0);
  2028.  
  2029.     if (!firstItem) {
  2030.       Cu.reportError("Unable to get CD Device: " + err);
  2031.       return;
  2032.     }
  2033.   } catch (err) {
  2034.     Cu.reportError("Unable to get CD Device: " + err);
  2035.     return;
  2036.   }
  2037.  
  2038.   var devMgr = Cc["@songbirdnest.com/Songbird/DeviceManager;2"]
  2039.                  .getService(Ci.sbIDeviceManager2);
  2040.   var device = devMgr.getDeviceForItem(firstItem);
  2041.   if (!device) {
  2042.     Cu.reportError("Unable to get CD Device");
  2043.     return;
  2044.   }
  2045.  
  2046.   // Invoke the CD Lookup
  2047.   var bag = Cc["@mozilla.org/hash-property-bag;1"]
  2048.               .createInstance(Ci.nsIPropertyBag2);
  2049.   device.submitRequest(Ci.sbICDDeviceEvent.REQUEST_CDLOOKUP, bag);
  2050. }
  2051.  
  2052. // The 'Show new items only' command for device trigger callback
  2053. function plCmd_ShowOnlyOnDevice_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2054.   // Get the current view and append a filter so we only get items that do
  2055.   // not have a known origin in the main library
  2056.   var playlist = unwrap(aContext.playlist);
  2057.   var view = playlist.mediaListView;
  2058.   var propIndex = view.cascadeFilterSet
  2059.                       .appendFilter(SBProperties.originIsInMainLibrary);
  2060.  
  2061.   // Constrain the filter to allow only items with '0' as
  2062.   // originIsInMainLibrary to be displayed.
  2063.   var constraints = [0];
  2064.   view.cascadeFilterSet.set(propIndex, constraints, constraints.length);
  2065.  
  2066.   // As we are now displaying only items on the device, refresh commands
  2067.   // so that 'Show new items' becomes 'Show all items'.
  2068.   playlist.refreshCommands();
  2069. }
  2070.  
  2071. // The 'Show all items' command for device trigger callback
  2072. function plCmd_ShowAllOnDevice_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2073.   // Get the current view and remove the originIsInMainLibrary filter
  2074.   var playlist = unwrap(aContext.playlist);
  2075.   var filterSet = playlist.mediaListView.cascadeFilterSet;
  2076.   for (var i = 0; i < filterSet.length; i++) {
  2077.     if (filterSet.getProperty(i) == SBProperties.originIsInMainLibrary) {
  2078.       filterSet.remove(i);
  2079.       break;
  2080.     }
  2081.   }
  2082.  
  2083.   // As we are now displaying all items on the device, refresh commands
  2084.   // so that 'Show all items' becomes 'Show new items'.
  2085.   playlist.refreshCommands();
  2086. }
  2087.  
  2088. // Given a playlist binding, grab all the items with the shouldRip property
  2089. // set to aVal and set them to aNewVal
  2090. function playlist_setRipProperty(aPlaylist, aVal, aNewVal) {
  2091.   var mediaList = aPlaylist.mediaListView.mediaList;
  2092.   mediaList.enumerateItemsByProperty(
  2093.                    "http://songbirdnest.com/data/1.0#shouldRip",
  2094.                    aVal,
  2095.                    {
  2096.                      onEnumerationBegin: function() { },
  2097.                      onEnumeratedItem: function(aList, aItem) {
  2098.                        aItem.setProperty(
  2099.                          "http://songbirdnest.com/data/1.0#shouldRip",
  2100.                          aNewVal);
  2101.                        return Ci.sbIMediaListEnumerationListener.CONTINUE;
  2102.                      },
  2103.                      onEnumerationEnd: function() { }
  2104.                    });
  2105.   aPlaylist.refreshCommands(false);
  2106.   return;
  2107. }
  2108.  
  2109. // Called when the select all cd info action is triggered
  2110. function plCmd_CheckAll_TriggerCallback(aContext,
  2111.                                          aSubMenuId, aCommandId, aHost) {
  2112.   var pls = unwrap(aContext.playlist);
  2113.   playlist_setRipProperty(pls, "0", "1");
  2114. }
  2115.  
  2116. function plCmd_UncheckAll_TriggerCallback(aContext,
  2117.                                          aSubMenuId, aCommandId, aHost) {
  2118.   var pls = unwrap(aContext.playlist);
  2119.   playlist_setRipProperty(pls, "1", "0");
  2120.   return;
  2121. }
  2122.  
  2123. // Called when the "burn to cd" action is triggered
  2124. function plCmd_BurnToCD_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2125.   // if something is selected, trigger the burn event on the playlist
  2126.   if (plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  2127.     unwrap(aContext.playlist).sendBurnToCDEvent();
  2128.   }
  2129. }
  2130.  
  2131. // Called when the "copy to device" action is triggered
  2132. function plCmd_CopyToDevice_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2133.   // if something is selected, trigger the burn event on the playlist
  2134.   if (plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  2135.     //XXX not implemented
  2136.     //unwrap(aContext.playlist).sendCopyToDeviceEvent();
  2137.   }
  2138. }
  2139.  
  2140. // Called when the "play playlist" action is triggered
  2141. function plCmd_PlayPlaylist_TriggerCallback(aContext,
  2142.                                             aSubMenuId, aCommandId, aHost) {
  2143.   var window = unwrap(aContext.window);
  2144.   var mediaList = unwrap(aContext.medialist);
  2145.   var gBrowser = window.gBrowser;
  2146.   var gMM = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
  2147.               .getService(Ci.sbIMediacoreManager);
  2148.   gBrowser.loadMediaList(mediaList);
  2149.   var view = mediaList.createView();
  2150.   gMM.sequencer.playView(view);
  2151. }
  2152.  
  2153. // Called when the "remove playlist" action is triggered
  2154. function plCmd_RemoveList_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2155.   unwrap(aContext.window).SBDeleteMediaList(aContext.medialist);
  2156. }
  2157.  
  2158. // Called when the "rename playlist" action is triggered
  2159. function plCmd_RenameList_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2160.   var window = unwrap(aContext.window);
  2161.   var medialist = unwrap(aContext.medialist);
  2162.   var servicePane = window.gServicePane;
  2163.   // If we have a servicetree, tell it to make the new playlist node editable
  2164.   if (servicePane) {
  2165.     var librarySPS = Cc['@songbirdnest.com/servicepane/library;1']
  2166.                        .getService(Ci.sbILibraryServicePaneService);
  2167.     // Find the servicepane node for our new medialist
  2168.     var node = librarySPS.getNodeForLibraryResource(medialist);
  2169.  
  2170.     if (node) {
  2171.       // Ask the service pane to start editing our new node
  2172.       // so that the user can give it a name
  2173.       servicePane.startEditingNode(node);
  2174.     } else {
  2175.       throw("Error: Couldn't find a service pane node for the list we just created\n");
  2176.     }
  2177.  
  2178.   // Otherwise pop up a dialog and ask for playlist name
  2179.   } else {
  2180.     var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"  ]
  2181.                           .getService(Ci.nsIPromptService);
  2182.  
  2183.     var input = {value: medialist.name};
  2184.     var title = SBString("renamePlaylist.title", "Rename Playlist");
  2185.     var prompt = SBString("renamePlaylist.prompt", "Enter the new name of the playlist.");
  2186.  
  2187.     if (promptService.prompt(window, title, prompt, input, null, {})) {
  2188.       medialist.name = input.value;
  2189.     }
  2190.   }
  2191. }
  2192.  
  2193. // Called when the queueNext action is triggered for a playlist
  2194. function plCmd_QueueListNext_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2195.   var mediaList = unwrap(aContext.medialist);
  2196.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2197.                        .getService(Ci.sbIPlayQueueService);
  2198.   queueService.queueNext(mediaList);
  2199. }
  2200.  
  2201. // Called when the queueLast action is triggered for a playlist
  2202. function plCmd_QueueListLast_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2203.   var mediaList = unwrap(aContext.medialist);
  2204.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2205.                        .getService(Ci.sbIPlayQueueService);
  2206.   queueService.queueLast(mediaList);
  2207. }
  2208.  
  2209. function plCmd_UpdateSmartPlaylist_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2210.   var medialist = unwrap(aContext.medialist);
  2211.   if (medialist instanceof Ci.sbILocalDatabaseSmartMediaList)
  2212.     medialist.rebuild();
  2213. }
  2214.  
  2215. function plCmd_EditSmartPlaylist_TriggerCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2216.   var medialist = unwrap(aContext.medialist);
  2217.   if (medialist instanceof Ci.sbILocalDatabaseSmartMediaList) {
  2218.     var watcher = Cc["@mozilla.org/embedcomp/window-watcher;1"]
  2219.                     .getService(Ci.nsIWindowWatcher);
  2220.     watcher.openWindow(aContext.window,
  2221.                        "chrome://songbird/content/xul/smartPlaylist.xul",
  2222.                        "_blank",
  2223.                        "chrome,resizable=yes,dialog=yes,centerscreen,modal,titlebar=no",
  2224.                        medialist);
  2225.     unwrap(aContext.playlist).refreshCommands();
  2226.   }
  2227. }
  2228.  
  2229. // Returns true when at least one track is selected in the playlist
  2230. function plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost) {
  2231.   return (unwrap(aContext.playlist).mediaListView.selection.count != 0);
  2232. }
  2233.  
  2234.  
  2235. // If we have any audio selected, show this command.
  2236. function plCmd_IsAnyAudioSelected(aContext, aSubMenuId, aCommandId, aHost) {
  2237.   var selection = unwrap(aContext.playlist).mediaListView.selection;
  2238.  
  2239.   // if the current media item is audio, just return.
  2240.   var item = selection.currentMediaItem;
  2241.   if (item && item.getProperty(SBProperties.contentType) == "audio") {
  2242.     return true;
  2243.   }
  2244.  
  2245.   if (selection.isContentTypeSelected("audio"))
  2246.     return true;
  2247.  
  2248.   return false;
  2249. }
  2250.  
  2251. // Returns true when the library is not read only.
  2252. function plCmd_IsMediaListReadOnly(aContext, aSubMenuId, aCommandId, aHost) {
  2253.   return (unwrap(aContext.playlist).mediaListView
  2254.                                    .mediaList
  2255.                                    .getProperty(SBProperties.isReadOnly) == "1");
  2256. }
  2257.  
  2258. // Returns true when "select all" should be visible, per comment #1 in
  2259. // bug 18049: It should default to 'Check All' unless all tracks are
  2260. // already checked, in which case it should say 'Uncheck All'. This means if the
  2261. // playlist is partially checked the button should read 'Check All' and to
  2262. // uncheck all tracks the user will need to click twice.
  2263. function plCmd_CheckAllVisibleCallback(aContext, aSubMenuId, aCommandId, aHost)
  2264. {
  2265.   var returnValue;
  2266.   var pls = unwrap(aContext.playlist);
  2267.   var checkedItemCount = 0;
  2268.  
  2269.   var mediaList = pls.mediaListView.mediaList;
  2270.   mediaList.enumerateItemsByProperty(
  2271.                    "http://songbirdnest.com/data/1.0#shouldRip",
  2272.                    "1",
  2273.                    {
  2274.                      onEnumerationBegin: function() { },
  2275.                      onEnumeratedItem: function(aList, aItem) {
  2276.                        checkedItemCount++;
  2277.                      },
  2278.                      onEnumerationEnd: function() { }
  2279.                    });
  2280.   returnValue = mediaList.length != checkedItemCount;
  2281.   return returnValue;
  2282. }
  2283.  
  2284. // Returns true when at least one track is selected in the playlist and none of the selected tracks have downloading forbidden
  2285. function plCmd_Download_EnabledCallback(aContext, aSubMenuId, aCommandId, aHost) {
  2286.   if (!plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  2287.     return false;
  2288.   }
  2289.   try {
  2290.     var playlist = unwrap(aContext.playlist);
  2291.     var window = unwrap(aContext.window);
  2292.     var enumerator = playlist.mediaListView.selection.selectedMediaItems;
  2293.     while (enumerator.hasMoreElements()) {
  2294.       var item = enumerator.getNext().QueryInterface(Ci.sbIMediaItem);
  2295.       if (!item) continue; // WTF?
  2296.       if (item.getProperty(SBProperties.disableDownload) == '1') {
  2297.         // one of the items has download disabled, we need to disable the command
  2298.         return false;
  2299.       }
  2300.     }
  2301.     // none of the items had download disabled, enable the command
  2302.     return true;
  2303.   } catch (e) {
  2304.     Cu.reportError(err);
  2305.     // something bad happened - I say no.
  2306.     return false;
  2307.   }
  2308. }
  2309.  
  2310. // Returns true if the 'rescan' item command is enabled
  2311. function plCmd_IsRescanItemEnabled(aContext, aSubMenuId, aCommandId, aHost) {
  2312.   var prefs = Cc["@mozilla.org/preferences-service;1"]
  2313.                 .getService(Ci.nsIPrefBranch2);
  2314.   var enabled = false;
  2315.   try {
  2316.    enabled = prefs.getBoolPref("songbird.commands.enableRescanItem");
  2317.   } catch (e) {
  2318.     // nothing to do
  2319.   }
  2320.   return enabled;
  2321. }
  2322.  
  2323. // Returns true if the 'reveal' command is enabled
  2324. function plCmd_isSelectionRevealable(aContext, aSubMenuId, aCommandId, aHost) {
  2325.   var selection = unwrap(aContext.playlist).mediaListView.selection;
  2326.   if (selection.count != 1) { return false; }
  2327.   var items = selection.selectedIndexedMediaItems;
  2328.   var item = items.getNext().QueryInterface(Ci.sbIIndexedMediaItem).mediaItem;
  2329.   return (item.contentSrc.scheme == "file")
  2330. }
  2331.  
  2332. // Returns true if the host is the shortcuts instantiator
  2333. function plCmd_IsShortcutsInstantiator(aContext, aSubMenuId, aCommandId, aHost) {
  2334.   return (aHost == "shortcuts");
  2335. }
  2336.  
  2337. // Returns true if the host is the toolbar instantiator
  2338. function plCmd_IsToolbarInstantiator(aContext, aSubMenuId, aCommandId, aHost) {
  2339.   return (aHost == "toolbar");
  2340. }
  2341.  
  2342. // Returns true if the current playlist isn't the library
  2343. function plCmd_IsNotLibraryContext(aContext, aSubMenuId, aCommandId, aHost) {
  2344.   var medialist = unwrap(aContext.medialist);
  2345.   return (medialist.library != medialist);
  2346. }
  2347.  
  2348. // Return true if the playlist is empty
  2349. function plCmd_IsNotEmptyPlaylist(aContext, aSubMenuId, aCommandId, ahost) {
  2350.   return !!(unwrap(aContext.medialist).length);
  2351. }
  2352.  
  2353. // Return true if the play queue context menu items should be enabled for
  2354. // the selected track(s).
  2355. function plCmd_ContextMenuQueueEnabled(aContext, aSubMenuId, aCommandId, aHost) {
  2356.   if (!plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost)) {
  2357.     return false;
  2358.   }
  2359.  
  2360.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2361.                        .getService(Ci.sbIPlayQueueService);
  2362.  
  2363.   return !queueService.operationInProgress;
  2364. }
  2365.  
  2366. // Return true if the play queue context menu items should be enabled for
  2367. // the selected list.
  2368. function plCmd_ListContextMenuQueueEnabled(aContext, aSubMenuId, aCommandId, aHost) {
  2369.   if (!plCmd_IsNotEmptyPlaylist(aContext, aSubMenuId, aCommandId, aHost)) {
  2370.     return false;
  2371.   }
  2372.  
  2373.   var queueService = Cc["@songbirdnest.com/Songbird/playqueue/service;1"]
  2374.                        .getService(Ci.sbIPlayQueueService);
  2375.  
  2376.   return !queueService.operationInProgress;
  2377. }
  2378.  
  2379. // Returns true if the playlist can be modified (is not read-only)
  2380. function plCmd_CanModifyPlaylist(aContext, aSubMenuId, aCommandId, aHost) {
  2381.   return !(plCmd_isReadOnlyLibrary(aContext, aSubMenuId, aCommandId, aHost) ||
  2382.            plCmd_isReadOnlyPlaylist(aContext, aSubMenuId, aCommandId, aHost));
  2383. }
  2384.  
  2385. // Returns true if the playlist can be added to the play queue
  2386. function plCmd_CanQueuePlaylist(aContext, aSubMenuId, aCommandId, aHost) {
  2387.  
  2388.   // Don't allow device playlists to be added to the play queue. See comments in
  2389.   // Bug 21895.
  2390.   var deviceManager = Cc["@songbirdnest.com/Songbird/DeviceManager;2"]
  2391.                         .getService(Ci.sbIDeviceManager2);
  2392.  
  2393.   // device will be null if the list is not in a device library
  2394.   var device = deviceManager.getDeviceForItem(unwrap(aContext.medialist));
  2395.  
  2396.   return !device;
  2397. }
  2398.  
  2399. // Returns true if the playlist content can be modified (is not read-only)
  2400. function plCmd_CanModifyPlaylistContent(aContext, aSubMenuId, aCommandId, aHost) {
  2401.   return !(plCmd_isReadOnlyLibraryContent(aContext, aSubMenuId, aCommandId, aHost) ||
  2402.            plCmd_isReadOnlyPlaylistContent(aContext, aSubMenuId, aCommandId, aHost));
  2403. }
  2404.  
  2405. // Returns true if the library the playlist is in is read-only
  2406. function plCmd_isReadOnlyLibrary(aContext, aSubMenuId, aCommandId, aHost) {
  2407.   var medialist = unwrap(aContext.medialist);
  2408.   return !medialist.library.userEditable;
  2409. }
  2410.  
  2411. // Returns true if the playlist is read-only
  2412. function plCmd_isReadOnlyPlaylist(aContext, aSubMenuId, aCommandId, aHost) {
  2413.   var medialist = unwrap(aContext.medialist);
  2414.   return !medialist.userEditable;
  2415. }
  2416.  
  2417. // Returns true if the library the playlist is in is read-only
  2418. function plCmd_isReadOnlyLibraryContent(aContext, aSubMenuId, aCommandId, aHost) {
  2419.   if (plCmd_isReadOnlyLibrary(aContext, aSubMenuId, aCommandId, aHost))
  2420.     return true;
  2421.   var medialist = unwrap(aContext.medialist);
  2422.   return !medialist.library.userEditableContent;
  2423. }
  2424.  
  2425. // Returns true if the playlist is read-only
  2426. function plCmd_isReadOnlyPlaylistContent(aContext, aSubMenuId, aCommandId, aHost) {
  2427.   if (plCmd_isReadOnlyPlaylist(aContext, aSubMenuId, aCommandId, aHost))
  2428.     return true;
  2429.   var medialist = unwrap(aContext.medialist);
  2430.   return !medialist.userEditableContent;
  2431. }
  2432.  
  2433. // Returns true if the conditions are ok for adding tracks to the library
  2434. function plCmd_CanAddToLibrary(aContext, aSubMenuId, aCommandId, aHost) {
  2435.   return plCmd_IsAnyTrackSelected(aContext, aSubMenuId, aCommandId, aHost) &&
  2436.          plCmd_CanModifyPlaylistContent(aContext, aSubMenuId, aCommandId, aHost) &&
  2437.          plCmd_IsNotLibraryContext(aContext, aSubMenuId, aCommandId, aHost);
  2438. }
  2439.  
  2440. // Returns true if a download is currently in progress (not paused)
  2441. function plCmd_IsDownloading(aContext, aSubMenuId, aCommandId, aHost) {
  2442.   var device = getDownloadDevice();
  2443.   if (!device) return false;
  2444.   var deviceState = device.getDeviceState('');
  2445.   return (deviceState == Ci.sbIDeviceBase.STATE_DOWNLOADING);
  2446. }
  2447.  
  2448. // Returns true if a download is currently paused
  2449. function plCmd_IsDownloadPaused(aContext, aSubMenuId, aCommandId, aHost) {
  2450.   var device = getDownloadDevice();
  2451.   if (!device) return false;
  2452.   var deviceState = device.getDeviceState('');
  2453.   return (deviceState == Ci.sbIDeviceBase.STATE_DOWNLOAD_PAUSED);
  2454. }
  2455.  
  2456. // Returns true if a download has been started, regardless of wether it has
  2457. // been paused or not
  2458. function plCmd_IsDownloadActive(aContext, aSubMenuId, aCommandId, aHost) {
  2459.   return plCmd_IsDownloading(aContext, aSubMenuId, aCommandId, aHost) ||
  2460.         plCmd_IsDownloadPaused(aContext, aSubMenuId, aCommandId, aHost);
  2461. }
  2462.  
  2463. // Returns true if a download is in progress or if there is not download that
  2464. // has been started at all
  2465. function plCmd_IsDownloadingOrNotActive(aContext, aSubMenuId, aCommandId, aHost) {
  2466.   return plCmd_IsDownloading(aContext, aSubMenuId, aCommandId, aHost) ||
  2467.         !plCmd_IsDownloadActive(aContext, aSubMenuId, aCommandId, aHost);
  2468. }
  2469.  
  2470. // Returns true if any completed download items exist
  2471. function plCmd_DownloadHasCompletedItems(aContext, aSubMenuId, aCommandId, aHost) {
  2472.   var device = getDownloadDevice();
  2473.   if (!device) return false;
  2474.   return (device.completedItemCount > 0);
  2475. }
  2476.  
  2477. // Returns true if there are items in the web media history
  2478. function plCmd_WebMediaHistoryHasItems(aContext, aSubMenuId, aCommandId, aHost) {
  2479.   var wl = getWebLibrary();
  2480.   return wl && !wl.isEmpty;
  2481. }
  2482.  
  2483. // Returns true if the supplied context contains a gBrowser object
  2484. function plCmd_ContextHasBrowser(aContext, aSubMenuId, aCommandId, aHost) {
  2485.   var window = unwrap(aContext.window);
  2486.   return (window.gBrowser);
  2487. }
  2488.  
  2489. // Returns true if the playlist is a smart playlist
  2490. function plCmd_isSmartPlaylist(aContext, aSubMenuId, aCommandId, aHost) {
  2491.   var medialist = unwrap(aContext.medialist);
  2492.   return (medialist.type == "smart");
  2493. }
  2494.  
  2495. function plCmd_isLiveUpdateSmartPlaylist(aContext, aSubMenuId, aCommandId, aHost) {
  2496.   var medialist = unwrap(aContext.medialist);
  2497.   if (medialist instanceof Ci.sbILocalDatabaseSmartMediaList)
  2498.     return medialist.autoUpdate;
  2499.   return false;
  2500. }
  2501.  
  2502. // Returns a function that will return the conjunction of the result of the inputs
  2503. function plCmd_AND( /* comma separated list (not array) of functions */ ) {
  2504.   var methods = Array.prototype.concat.apply([], arguments);
  2505.   return function _plCmd_Conjunction(aContext, aSubMenuId, aCommandId, aHost) {
  2506.     for each (var f in methods) {
  2507.       if (!f(aContext, aSubMenuId, aCommandId, aHost))
  2508.         return false;
  2509.     }
  2510.     return true;
  2511.   }
  2512. }
  2513.  
  2514. // Returns a function that will return the disjunction of the result of the inputs
  2515. function plCmd_OR( /* comma separated list (not array) of functions */ ) {
  2516.   var methods = Array.prototype.concat.apply([], arguments);
  2517.   return function _plCmd_Disjunction(aContext, aSubMenuId, aCommandId, aHost) {
  2518.     for each (var f in methods) {
  2519.       if (f(aContext, aSubMenuId, aCommandId, aHost))
  2520.         return true;
  2521.     }
  2522.     return false;
  2523.   }
  2524. }
  2525.  
  2526. // Returns a function that will return the negation of the result of the input
  2527. function plCmd_NOT( aFunction ) {
  2528.   return function _plCmd_Negation(aContext, aSubMenuId, aCommandId, aHost) {
  2529.     return !aFunction(aContext, aSubMenuId, aCommandId, aHost);
  2530.   }
  2531. }
  2532.  
  2533. // Always return false
  2534. function plCmd_False(aContext, aSubMenuId, aCommandId, aHost) {
  2535.   return false
  2536. }
  2537.  
  2538. function onBrowserTransfer(mediaItems, parentWindow)
  2539. {
  2540.   var ddh =
  2541.     Cc["@songbirdnest.com/Songbird/DownloadDeviceHelper;1"]
  2542.       .getService(Ci.sbIDownloadDeviceHelper);
  2543.   ddh.downloadSome(mediaItems);
  2544. }
  2545.  
  2546. var g_downloadDevice = null;
  2547. function getDownloadDevice() {
  2548.   try
  2549.   {
  2550.     if (!g_downloadDevice) {
  2551.       var deviceManager = Cc["@songbirdnest.com/Songbird/DeviceManager;1"]
  2552.                             .getService(Ci.sbIDeviceManager);
  2553.  
  2554.       if (deviceManager)
  2555.       {
  2556.         var downloadCategory = 'Songbird Download Device';
  2557.         if (deviceManager.hasDeviceForCategory(downloadCategory))
  2558.         {
  2559.           g_downloadDevice = deviceManager.getDeviceByCategory(downloadCategory);
  2560.           g_downloadDevice = g_downloadDevice.QueryInterface
  2561.                                       (Ci.sbIDownloadDevice);
  2562.         }
  2563.       }
  2564.     }
  2565.     return g_downloadDevice;
  2566.   } catch(e) {
  2567.     Cu.reportError(e);
  2568.   }
  2569.   return null;
  2570. }
  2571.  
  2572. var g_webLibrary = null
  2573. function getWebLibrary() {
  2574.   try {
  2575.     if (g_webLibrary == null) {
  2576.       var prefs = Cc["@mozilla.org/preferences-service;1"]
  2577.         .getService(Ci.nsIPrefBranch2);
  2578.       var webListGUID = prefs.getComplexValue("songbird.library.web",
  2579.           Ci.nsISupportsString);
  2580.       var libraryManager =
  2581.         Cc["@songbirdnest.com/Songbird/library/Manager;1"]
  2582.           .getService(Ci.sbILibraryManager);
  2583.       g_webLibrary = libraryManager.getLibrary(webListGUID);
  2584.     }
  2585.   } catch(e) {
  2586.     Cu.reportError(e);
  2587.   }
  2588.  
  2589.   return g_webLibrary;
  2590. }
  2591.  
  2592. function plCmd_ShowDefaultInToolbarCheck(aContext, aHost) {
  2593.   if (aHost == "toolbar") {
  2594.     if (dataRemote("commands.showdefaultintoolbar", null).boolValue) return true;
  2595.     return false;
  2596.   }
  2597.   return true;
  2598. }
  2599.  
  2600. function plCmd_HideForToolbarCheck(aContext, aHost) {
  2601.   return (aHost != "toolbar");
  2602. }
  2603.  
  2604. function plCmd_ShowForToolbarCheck(aContext, aHost) {
  2605.   return (aHost == "toolbar");
  2606. }
  2607.  
  2608. // Return true if we are currently showing only device only tracks
  2609. // (i.e. if there is a filter in place for originIsInMainLibrary)
  2610. function isShowingDeviceOnly(playlist) {
  2611.   var filterSet = playlist.mediaListView.cascadeFilterSet;
  2612.   for (var i = 0; i < filterSet.length; i++) {
  2613.     if (filterSet.getProperty(i) === SBProperties.originIsInMainLibrary) {
  2614.       return true;
  2615.     }
  2616.   }
  2617.   return false;
  2618. }
  2619.  
  2620. // 'Show new items only' device playlist command visibility callback
  2621. function plCmd_ShowOnlyOnDevice_VisibleCallback(aContext, aHost) {
  2622.   var playlist = unwrap(aContext.playlist);
  2623.   return (aHost == "toolbar" && !isShowingDeviceOnly(playlist));
  2624. }
  2625.  
  2626. // 'Show all items' device playlist command visibility callback
  2627. function plCmd_ShowAllOnDevice_VisibleCallback(aContext, aHost) {
  2628.   var playlist = unwrap(aContext.playlist);
  2629.   return (aHost == "toolbar" && isShowingDeviceOnly(playlist));
  2630. }
  2631.  
  2632. function plCmd_DownloadInit(aContext, aHost) {
  2633.   var implementorContext = {
  2634.     context: aContext,
  2635.     batchHelper: new LibraryUtils.BatchHelper(),
  2636.     needRefresh: false,
  2637.  
  2638.     // sbIDeviceBaseCallback
  2639.     onTransferComplete: function(aMediaItem, aStatus) {
  2640.       this.refreshCommands();
  2641.     },
  2642.  
  2643.     onStateChanged: function(aDeviceIdentifier, aState) {
  2644.       this.refreshCommands();
  2645.     },
  2646.  
  2647.     onDeviceConnect: function(aDeviceIdentifier) {},
  2648.     onDeviceDisconnect: function(aDeviceIdentifier) {},
  2649.     onTransferStart: function(aMediaItem) {},
  2650.  
  2651.  
  2652.     // sbIMediaListListener
  2653.     onAfterItemRemoved: function(aMediaList, aMediaItem) {
  2654.       return this.onMediaListChanged();
  2655.     },
  2656.  
  2657.     onBeforeListCleared: function(aMediaList, aExcludeLists) {
  2658.       return true;
  2659.     },
  2660.  
  2661.     onListCleared: function(aMediaList, aExcludeLists) {
  2662.       return this.onMediaListChanged();
  2663.     },
  2664.  
  2665.     onBatchBegin: function(aMediaList) {
  2666.       this.batchHelper.begin();
  2667.     },
  2668.  
  2669.     onBatchEnd: function(aMediaList) {
  2670.       this.batchHelper.end();
  2671.       if (!this.batchHelper.isActive() && this.needRefresh) {
  2672.         this.refreshCommands();
  2673.         this.needRefresh = false;
  2674.       }
  2675.     },
  2676.  
  2677.     onItemAdded: function(aMediaList, aMediaItem, aIndex) { return true; },
  2678.     onBeforeItemRemoved: function(aMediaList, aMediaItem, aIndex) {
  2679.       return true;
  2680.     },
  2681.     onItemUpdated: function(aMediaList, aMediaItem, aProperties) {
  2682.       return true;
  2683.     },
  2684.     onItemMoved: function(aMediaList, aFromIndex, aToIndex) { return true; },
  2685.  
  2686.  
  2687.     onMediaListChanged: function() {
  2688.       if (this.batchHelper.isActive()) {
  2689.         this.needRefresh = true;
  2690.         return true;
  2691.       }
  2692.       this.refreshCommands();
  2693.       return false;
  2694.     },
  2695.  
  2696.     refreshCommands: function() {
  2697.       var playlist = unwrap(this.context.playlist);
  2698.       if (playlist)
  2699.         playlist.refreshCommands();
  2700.     }
  2701.   };
  2702.  
  2703.   var device = getDownloadDevice();
  2704.   if (!device) return false;
  2705.   device.addCallback(implementorContext);
  2706.   device.downloadMediaList.addListener
  2707.                               (implementorContext,
  2708.                                false,
  2709.                                Ci.sbIMediaList.LISTENER_FLAGS_AFTERITEMREMOVED |
  2710.                                Ci.sbIMediaList.LISTENER_FLAGS_LISTCLEARED |
  2711.                                Ci.sbIMediaList.LISTENER_FLAGS_BATCHBEGIN |
  2712.                                Ci.sbIMediaList.LISTENER_FLAGS_BATCHEND);
  2713.   aContext.implementorContext = implementorContext;
  2714. }
  2715.  
  2716. function plCmd_DownloadShutdown(aContext, aHost) {
  2717.   var device = getDownloadDevice();
  2718.   if (!device) return false;
  2719.   if (aContext.implementorContext) {
  2720.     device.removeCallback(aContext.implementorContext);
  2721.     device.downloadMediaList.removeListener(aContext.implementorContext);
  2722.   }
  2723.   aContext.implementorContext = null;
  2724. }
  2725.  
  2726. var g_dataRemoteService = null;
  2727. function dataRemote(aKey, aRoot) {
  2728.   if (!g_dataRemoteService) {
  2729.     g_dataRemoteService = new Components.
  2730.       Constructor( "@songbirdnest.com/Songbird/DataRemote;1",
  2731.                   Ci.sbIDataRemote,
  2732.                   "init");
  2733.   }
  2734.   return g_dataRemoteService(aKey, aRoot);
  2735. }
  2736.  
  2737. function LOG(str) {
  2738.   var consoleService = Cc['@mozilla.org/consoleservice;1']
  2739.                          .getService(Ci.nsIConsoleService);
  2740.   consoleService.logStringMessage(str);
  2741.   dump(str+"\n");
  2742. };
  2743.  
  2744. function NSGetModule(compMgr, fileSpec) {
  2745.   return XPCOMUtils.generateModule([PublicPlaylistCommands],
  2746.   function(aCompMgr, aFileSpec, aLocation) {
  2747.     XPCOMUtils.categoryManager.addCategoryEntry(
  2748.       "app-startup",
  2749.       PublicPlaylistCommands.prototype.classDescription,
  2750.       "service," + PublicPlaylistCommands.prototype.contractID,
  2751.       true,
  2752.       true);
  2753.   });
  2754. }
  2755.