head_mediaexportservice.js
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2009 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
28 Components.utils.import("resource://app/jsmodules/ArrayConverter.jsm");
29 
30 // Export data file constants
31 // NOTE: When changing these constants, be sure to update the file
32 // 'sbMediaExportDefines.h' as welll!
33 var TASKFILE_NAME = "songbird_export.task";
35 var TASKFILE_SCHEMAVERSION_HEADER = "schema-version";
36 var TASKFILE_ADDEDMEDIALISTS_HEADER = "added-medialists";
37 var TASKFILE_REMOVEDMEDIALISTS_HEADER = "removed-medialists";
38 var TASKFILE_ADDEDMEDIAITEMS_HEADER = "added-mediaitems";
39 var TASKFILE_UPDATEDMEDIAITEMS_HEADER = "updated-mediaitems";
40 
41 // Media exporter prefs.
43  "songbird.library_importexport.autoshutdown";
45  "songbird.library_importexport.autostartup";
47  "songbird.library_exporter.export_tracks";
49  "songbird.library_exporter.export_playlists";
51  "songbird.library_exporter.export_smartplaylists";
53  "songbird.library_exporter.start_agent"
54 
55 var AppPrefs = Cc["@mozilla.org/fuel/application;1"]
56  .getService(Ci.fuelIApplication).prefs;
57 
58 //------------------------------------------------------------------------------
59 // File management utils
60 
61 function newTestFileURI(aFileName) {
62  var fileClone = TEST_FILES.clone();
63  fileClone.append(aFileName);
64 
65  return newFileURI(fileClone);
66 }
67 
69 {
70  var taskFileFolder = Cc["@mozilla.org/file/directory_service;1"]
71  .getService(Ci.nsIProperties)
72  .get("AppRegD", Ci.nsIFile);
73 
74  var entries = taskFileFolder.directoryEntries;
75  while (entries.hasMoreElements()) {
76  var curFile = entries.getNext().QueryInterface(Ci.nsIFile);
77 
78  if (curFile.leafName.indexOf(TASKFILE_NAME) > -1) {
79  curFile.remove(false);
80  }
81  }
82 }
83 
85 {
86  var dataFile = Cc["@mozilla.org/file/directory_service;1"]
87  .getService(Ci.nsIProperties)
88  .get("AppRegD", Ci.nsIFile);
89  dataFile.append(TASKFILE_NAME);
90  return dataFile;
91 }
92 
93 function newLineInputStream(aFile)
94 {
95  var stream = Cc["@mozilla.org/network/file-input-stream;1"]
96  .createInstance(Ci.nsIFileInputStream);
97  stream.init(aFile, 0x1, 0, 0);
98  stream.QueryInterface(Ci.nsILineInputStream);
99  return stream;
100 }
101 
102 //------------------------------------------------------------------------------
103 // Media export pref management
104 
105 //
106 // \brief Turn off all media exporting.
107 //
109 {
110  AppPrefs.setValue(PREF_EXPORT_TRACKS, false);
111  AppPrefs.setValue(PREF_EXPORT_PLAYLISTS, false);
112  AppPrefs.setValue(PREF_EXPORT_SMARTPLAYLISTS, false);
113  AppPrefs.setValue(PREF_EXPORT_STARTAGENT, false);
114 }
115 
116 //
117 // \brief Toggle exporting to only do tracks to the main library.
118 //
120 {
121  AppPrefs.setValue(PREF_EXPORT_TRACKS, true);
122  AppPrefs.setValue(PREF_EXPORT_PLAYLISTS, false);
123  AppPrefs.setValue(PREF_EXPORT_SMARTPLAYLISTS, false);
124  AppPrefs.setValue(PREF_EXPORT_STARTAGENT, false);
125 }
126 
127 //
128 // \brief Toggle exporting of tracks and regular playlists (not smart).
129 //
131 {
132  AppPrefs.setValue(PREF_EXPORT_TRACKS, true);
133  AppPrefs.setValue(PREF_EXPORT_PLAYLISTS, true);
134  AppPrefs.setValue(PREF_EXPORT_SMARTPLAYLISTS, false);
135  AppPrefs.setValue(PREF_EXPORT_STARTAGENT, false);
136 }
137 
138 //
139 // \brief Toggle exporting of tracks, regular playlists, and smart playlists.
140 //
142 {
143  AppPrefs.setValue(PREF_EXPORT_TRACKS, true);
144  AppPrefs.setValue(PREF_EXPORT_PLAYLISTS, true);
145  AppPrefs.setValue(PREF_EXPORT_SMARTPLAYLISTS, true);
146  AppPrefs.setValue(PREF_EXPORT_STARTAGENT, false);
147 }
148 
149 //------------------------------------------------------------------------------
150 // Export task data parser utility class.
151 // NOTE: This parser is only used for the unit tests and should not be used as
152 // an example in real life.
153 // @see bug 16221 for parer upgrading.
154 
155 function TaskFileDataParser(aDataFile)
156 {
157  this._dataFile = aDataFile;
158  this._addedMediaLists = [];
159  this._removedMediaLists = [];
160  this._addedMediaItems = {};
161  this._curMediaListName = "";
162  this._curParseMode = -1;
163 
164  // Do the parse now
165  this._parseDataFile();
166 }
167 
169 {
170  // Added resource getters
171  getAddedMediaLists: function() {
172  return this._addedMediaLists;
173  },
174  getRemovedMediaLists: function() {
175  return this._removedMediaLists;
176  },
177  getAddedMediaItems: function() {
178  return this._addedMediaItems;
179  },
180 
181  // Internal parse mode states
182  _STATE_MODE_ADDEDMEDIALISTS : 1,
183  _STATE_MODE_REMOVEDMEDIALISTS : 2,
184  _STATE_MODE_ADDEDMEDIAITEMS : 3,
185 
186  _parseDataFile: function() {
187  var inputStream = newLineInputStream(this._dataFile);
188 
189  var curLine = {};
190  var hasMore = true;
191  var hasSchema = false;
192  var nextItem = 0;
193  var result;
194 
195  while (hasMore) {
196  hasMore = inputStream.readLine(curLine);
197  dump(curLine.value + "\n");
198 
199  if (curLine.value == "") {
200  // empty line
201  continue;
202  }
203  else if ((result = /^\[(.*?)(?::(.*))?\]$/(curLine.value))) {
204  // this is a section header
205  nextItem = 0;
206  switch(result[1]) {
207  case TASKFILE_SCHEMAVERSION_HEADER:
208  assertEqual(result[2], TASKFILE_SCHEMAVERSION,
209  "schema version mismatch");
210  hasSchema = true;
211  break;
212  case TASKFILE_ADDEDMEDIALISTS_HEADER:
213  assertEqual(result[2], null,
214  "unexpected junk in add media lists header");
215  this._curParseMode = this._STATE_MODE_ADDEDMEDIALISTS;
216  break;
217  case TASKFILE_REMOVEDMEDIALISTS_HEADER:
218  assertEqual(result[2], null,
219  "unexpected junk in remove media lists header");
220  this._curParseMode = this._STATE_MODE_REMOVEDMEDIALISTS;
221  break;
222  case TASKFILE_ADDEDMEDIAITEMS_HEADER:
223  this._curParseMode = this._STATE_MODE_ADDEDMEDIAITEMS;
224  assertNotEqual(result[2], null, "No media list name found");
225  // remember to decode UTF8 encoded list name
226  this._curMediaListName = decodeURIComponent(result[2]);
227  break;
228  default:
229  doFail('Unexpected section header "' + escape(result[1]) + '"');
230  }
231  }
232  else if ((result = /^(\d+)=(.*)$/(curLine.value))) {
233  // this is an added-to-medialist or removed item
234  assertEqual(result[1], nextItem, "items out of order");
235  nextItem++;
236  // all names are in utf8
237  var curValue = decodeURIComponent(result[2]);
238  switch (this._curParseMode) {
239  case this._STATE_MODE_ADDEDMEDIALISTS:
240  this._addedMediaLists.push(curValue);
241  break;
242 
243  case this._STATE_MODE_REMOVEDMEDIALISTS:
244  this._removedMediaLists.push(curValue);
245  break;
246 
247  default:
248  doFail("Unexpected state " + this._curParseMode);
249  }
250  }
251  else if ((result = /^([0-9a-f-]{36})=(.*)$/(curLine.value))) {
252  // this is an added item
253  // all names are in utf8
254  var curValue = decodeURIComponent(result[2]);
255  switch (this._curParseMode) {
256  case this._STATE_MODE_ADDEDMEDIAITEMS:
257  if (!this._addedMediaItems[this._curMediaListName]) {
258  this._addedMediaItems[this._curMediaListName] = [];
259  }
260  this._addedMediaItems[this._curMediaListName].push(curValue);
261  break;
262 
263  default:
264  doFail("Unexpected state " + this._curParseMode);
265  }
266  }
267  else {
268  doFail("Unexpected line " + curLine.value);
269  }
270  }
271 
272  assertTrue(hasSchema, "No schema version information found");
273 
274  inputStream.close();
275  },
276 };
function setExportNothing()
const Cc
function getExportedTaskFile()
function assertNotEqual(aExpected, aActual, aMessage)
var TASKFILE_SCHEMAVERSION
var TASKFILE_REMOVEDMEDIALISTS_HEADER
var PREF_EXPORT_STARTAGENT
var PREF_EXPORT_PLAYLISTS
function assertTrue(aTest, aMessage)
var TASKFILE_NAME
function assertEqual(aExpected, aActual, aMessage)
var TEST_FILES
function TaskFileDataParser(aDataFile)
function removeAllTaskFiles()
function d(s)
var PREF_EXPORT_SMARTPLAYLISTS
var TASKFILE_ADDEDMEDIALISTS_HEADER
var PREF_EXPORT_TRACKS
var TASKFILE_ADDEDMEDIAITEMS_HEADER
function newLineInputStream(aFile)
function newFileURI(file)
function setExportTracksPlaylistsSmartPlaylists()
function setExportTracksPlaylists()
return null
Definition: FeedWriter.js:1143
#define TASKFILE_SCHEMAVERSION_HEADER
var TASKFILE_UPDATEDMEDIAITEMS_HEADER
var PREF_IMPORTEXPORT_ONSHUTDOWN
StringArrayEnumerator prototype hasMore
function newTestFileURI(aFileName)
function setExportTracksOnly()
var PREF_IMPORTEXPORT_ONSTARTUP
const Ci
function doFail(text)