directory.js
Go to the documentation of this file.
1 if (typeof(Cc) == "undefined")
2  var Cc = Components.classes;
3 if (typeof(Ci) == "undefined")
4  var Ci = Components.interfaces;
5 if (typeof(Cu) == "undefined")
6  var Cu = Components.utils;
7 
8 Cu.import("resource://shoutcast-radio/Utils.jsm");
9 
10 if (typeof(songbirdMainWindow) == "undefined")
11  var songbirdMainWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
12  .getService(Ci.nsIWindowMediator)
13  .getMostRecentWindow("Songbird:Main").window;
14 
15 if (typeof(gBrowser) == "undefined")
16  var gBrowser = Cc["@mozilla.org/appshell/window-mediator;1"]
17  .getService(Ci.nsIWindowMediator)
18  .getMostRecentWindow("Songbird:Main").window.gBrowser;
19 
20 if (typeof(ioService) == "undefined")
21  var ioService = Cc["@mozilla.org/network/io-service;1"]
22  .getService(Ci.nsIIOService);
23 
24 #ifdef METRICS_ENABLED
25 if (typeof(gMetrics) == "undefined")
26  var gMetrics = Cc["@songbirdnest.com/Songbird/Metrics;1"]
27  .createInstance(Ci.sbIMetrics);
28 #endif
29 
30 const shoutcastTempLibGuid = "extensions.shoutcast-radio.templib.guid";
31 const shoutcastLibraryGuid = "extensions.shoutcast-radio.library.guid";
32 const shoutcastPlaylistInit = "extensions.shoutcast-radio.plsinit";
33 const shoutcastGenre = "extensions.shoutcast-radio.genre";
34 const shoutcastMinBitRate = "extensions.shoutcast-radio.min-bit-rate";
35 const shoutcastMinListeners = "extensions.shoutcast-radio.min-listeners";
36 const shoutcastCheckBitRate = "extensions.shoutcast-radio.limit-bit-rate";
37 const shoutcastCheckListeners = "extensions.shoutcast-radio.limit-listeners";
38 const defaultGenre = "sbITop";
39 
40 if (typeof(kPlaylistCommands) == "undefined") {
41  Cu.import("resource://app/components/kPlaylistCommands.jsm");
42  if (!kPlaylistCommands)
43  throw new Error("Import of kPlaylistCommands module failed!");
44 }
45 
46 if (typeof(SBProperties) == "undefined") {
47  Cu.import("resource://app/jsmodules/sbProperties.jsm");
48  if (!SBProperties)
49  throw new Error("Import of sbProperties module failed");
50 }
51 
52 if (typeof(LibraryUtils) == "undefined") {
53  Cu.import("resource://app/jsmodules/sbLibraryUtils.jsm");
54  if (!LibraryUtils)
55  throw new Error("Import of sbLibraryUtils module failed");
56 }
57 
58 var RadioDirectory = {
59  playlist : null,
60  tempLib : null,
61  favesList : null,
62  streamList : null,
63  favouriteIDs : null,
64  radioLib : null,
65 
66  init : function() {
67  var servicePaneStrings = Cc["@mozilla.org/intl/stringbundle;1"]
68  .getService(Ci.nsIStringBundleService)
69  .createBundle("chrome://shoutcast-radio/locale/overlay.properties");
70  // Set the tab title
71  document.title = servicePaneStrings.GetStringFromName("radioTabTitle");
72 
73 #ifdef METRICS_ENABLED
74  // the # of times the directory is loaded (corresponds to the # of
75  // times the servicepane is clicked, though also works if the user
76  // for some reason or another bookmarks it separately)
77  gMetrics.metricsInc("shoutcast", "directory", "loaded");
78 #endif
79 
80  var genre;
81  this._strings = document.getElementById("shoutcast-radio-strings");
82  if (Application.prefs.has(shoutcastGenre)) {
83  // load our old genre
84  genre = Application.prefs.getValue(shoutcastGenre, defaultGenre);
85  } else {
86  // no genre chosen, use the default genre
87  genre = defaultGenre;
88  Application.prefs.setValue(shoutcastGenre, genre);
89  }
90 
91  var menulist = document.getElementById("shoutcast-genre-menulist");
92  var strings = Cc["@mozilla.org/intl/stringbundle;1"]
93  .getService(Ci.nsIStringBundleService)
94  .createBundle("chrome://shoutcast-radio/locale/genres.properties");
95  var genres = this.getGenres(strings);
96 
97  // Add the "Top Stations" item first
98  menulist.appendItem(strings.GetStringFromName("genreTOP"), "sbITop");
99  menulist.menupopup.appendChild(document.createElementNS(
100  "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
101  "menuseparator"));
102 
103  // Build the menulist
104  var found = false;
105  for (i in genres) {
106  var thisgenre = genres[i];
107  var el = menulist.appendItem(thisgenre.label, thisgenre.value);
108  if (genre == thisgenre.value) {
109  menulist.selectedItem = el;
110  found = true;
111  }
112  }
113  if (!found)
114  menulist.selectedIndex = 0;
115 
116  this.favouriteIDs = [];
117 
118  // Setup our references to the SHOUTcast libraries
119  this.getLibraries();
120 
121  // Bind the playlist widget to our library
122  this.playlist = document.getElementById("shoutcast-directory");
123  var libraryManager = Cc['@songbirdnest.com/Songbird/library/Manager;1']
124  .getService(Ci.sbILibraryManager);
125  this.playlist.bind(this.radioLib.createView());
126 
127  // Enumerate all columns in the playlist
128  var playlistcolumns = this.playlist.tree.columns;
129  var columnbinds = [];
130  for (var i = 0; i < playlistcolumns.length; i++)
131  {
132  // Get the bind url for each column
133  columnbinds.push(
134  playlistcolumns.getColumnAt(i).element.getAttribute("bind"));
135  }
136  // If this is the first time we've loaded the playlist or we have
137  // no Name column, clear the normal columns and use the stream ones
138  if (!Application.prefs.getValue(shoutcastPlaylistInit, false) ||
139  (columnbinds.indexOf(SC_streamName) == -1))
140  {
141  Application.prefs.setValue(shoutcastPlaylistInit, true);
142  var colSpec = SC_streamName + " 358 " + SC_bitRate + " 71 " +
143  SC_comment + " 240 " + SC_listenerCount + " 74 " +
144  SC_bookmark + " 55";
145  this.radioLib.setProperty(SBProperties.defaultColumnSpec, colSpec);
146  this.playlist.clearColumns();
147  this.playlist.appendColumn(SC_streamName, "358");
148  this.playlist.appendColumn(SC_bitRate, "71");
149  this.playlist.appendColumn(SC_comment, "240");
150  this.playlist.appendColumn(SC_listenerCount, "74");
151  this.playlist.appendColumn(SC_bookmark, "55");
152  }
153 
154  var ldtv = this.playlist.tree.view
155  .QueryInterface(Ci.sbILocalDatabaseTreeView);
156  ldtv.setSort(SC_listenerCount, 0);
157 
158  this.playlist.addEventListener("PlaylistCellClick",
159  onPlaylistCellClick, false);
160  this.playlist.addEventListener("Play", onPlay, false);
161 
162  // Load the tracks for our selected genre
163  this.loadTable(genre);
164 
165  // Reload the filter value
166  var filterValue = Application.prefs.getValue(
167  "extensions.shoutcast-radio.filter", "");
168  if (filterValue != "") {
169  document.getElementById("filter").value = filterValue;
170  this.setFilter(filterValue);
171  }
172  },
173 
174  getGenres : function(strings) {
175  if (!strings) {
176  // Read in our list of genre strings
177  var strings = Cc["@mozilla.org/intl/stringbundle;1"]
178  .getService(Ci.nsIStringBundleService).createBundle(
179  "chrome://shoutcast-radio/locale/genres.properties");
180  }
181  var iter = strings.getSimpleEnumeration();
182  var genres = new Array();
183  while (iter.hasMoreElements()) {
184  var genreProp = iter.getNext()
185  .QueryInterface(Ci.nsIPropertyElement);
186  var genreValue = genreProp.key.substr(5);
187  var genreLabel = genreProp.value;
188  if (genreValue == "TOP")
189  continue;
190  genres.push({value:genreValue, label:genreLabel});
191  }
192 
193  // Add our custom genres
194  var customGenres = Application.prefs.getValue(
195  "extensions.shoutcast-radio.custom-genres", "").split(",");
196  for (i in customGenres) {
197  if (customGenres[i].length > 0) {
198  var custom = customGenres[i];
199  custom = custom.replace(/^\s*/,'').replace(/\s*$/,'');
200  genres.push({value:custom, label:custom});
201  }
202  }
203 
204  // Sort our genres
205  genres.sort(function(a,b) {
206  return (a.label.toUpperCase() > b.label.toUpperCase());
207  });
208 
209  return genres;
210  },
211 
212  unload: function() {
213  RadioDirectory.playlist.removeEventListener("PlaylistCellClick",
214  onPlaylistCellClick, false);
215  RadioDirectory.playlist.removeEventListener("Play", onPlay, false);
216  },
217  getLibraries : function() {
218  var libraryManager = Cc["@songbirdnest.com/Songbird/library/Manager;1"]
219  .getService(Ci.sbILibraryManager);
220 
221  var libGuid = Application.prefs.getValue(shoutcastLibraryGuid, "");
222  if (libGuid != "") {
223  try {
224  this.radioLib = libraryManager.getLibrary(libGuid);
225  } catch (e){
226  // If we have an invalid GUID, we act like we have no GUID
227  libGuid = "";
228  }
229  }
230  if (libGuid == "") {
231  this.radioLib = createLibrary("shoutcast_radio_library", null,
232  false);
233  // doesn't manifest itself in any user visible way, so i think
234  // it's safe to not localise
235  this.radioLib.name = "SHOUTcast Radio";
236  this.radioLib.setProperty(SBProperties.hidden, "1");
237  dump("*** Created SHOUTcast Radio library, GUID: " +
238  this.radioLib.guid);
239  libraryManager.registerLibrary(this.radioLib, true);
240  Application.prefs.setValue(shoutcastLibraryGuid,
241  this.radioLib.guid);
242  }
243 
244  libGuid = Application.prefs.getValue(shoutcastTempLibGuid, "");
245  if (libGuid != "") {
246  try {
247  this.tempLib = libraryManager.getLibrary(libGuid);
248  } catch (e) {
249  libGuid = "";
250  // Ensure null so the following part can't be executed if
251  // we have no library
252  this.tempLib = null;
253  }
254 
255  if (this.tempLib) {
256  // Get our favourites & stream lists
257  var a = this.tempLib.getItemsByProperty(
258  SBProperties.customType, "radio_favouritesList");
259  this.favesList = a.queryElementAt(0, Ci.sbIMediaList);
260  a = this.tempLib.getItemsByProperty(
261  SBProperties.customType, "radio_tempStreamList");
262  this.streamList = a.queryElementAt(0, Ci.sbIMediaList);
263  }
264  }
265  if (libGuid == "") {
266  this.tempLib = createLibrary("shoutcast_temp_library", null,
267  false);
268  // doesn't manifest itself in any user visible way, so i think
269  // it's safe to not localise
270  this.tempLib.name = "Temporary Library";
271  this.tempLib.setProperty(SBProperties.hidden, "1");
272  this.tempLib.setProperty(SBProperties.isReadOnly, "1");
273  dump("*** Created SHOUTcast Temporary Radio library, GUID: " +
274  this.tempLib.guid);
275  libraryManager.registerLibrary(this.tempLib, true);
276  Application.prefs.setValue(shoutcastTempLibGuid,
277  this.tempLib.guid);
278 
279  // the library might already exist in which case it might
280  // already have a faveslist - look for it
281  var propExists = true;
282  var a;
283  try {
284  a = this.tempLib.getItemsByProperty(
285  SBProperties.customType, "radio_favouritesList");
286  } catch (e) {
287  propExists = false;
288  }
289  if (propExists && a.length > 0) {
290  this.favesList = a.queryElementAt(0, Ci.sbIMediaList);
291  } else {
292  // both our favourites list and the temporary current-stream
293  // list will be children of this tempLib
294  this.favesList = this.tempLib.createMediaList("simple");
295  this.favesList.setProperty(SBProperties.hidden, "1");
296  this.favesList.setProperty(SBProperties.isReadOnly, "1");
297  }
298 
299  // Set the "Favourite Stations" name
300  this.favesList.name = this._strings.getString("favourites");
301  var colSpec = SC_streamName + " 358 " + SC_bitRate + " 71 " +
302  SC_comment + " 240 " + SC_listenerCount + " 74 " +
303  SC_bookmark + " 55";
304  this.favesList.setProperty(SBProperties.columnSpec, colSpec);
305  this.favesList.setProperty(SBProperties.defaultColumnSpec,colSpec);
306 
307  // Set the Media View to be list only (not filter)
308  var mpManager = Cc["@songbirdnest.com/Songbird/MediaPageManager;1"]
309  .getService(Ci.sbIMediaPageManager);
310  var pages = mpManager.getAvailablePages(this.favesList);
311  var listView = null;
312  while (pages.hasMoreElements()) {
313  var pageInfo = pages.getNext();
314  pageInfo.QueryInterface(Ci.sbIMediaPageInfo);
315  if (pageInfo.contentUrl ==
316  "chrome://songbird/content/mediapages/playlistPage.xul")
317  listView = pageInfo;
318  }
319  if (listView)
320  mpManager.setPage(this.favesList, listView)
321 
322  // temporary playlist to hold the current stream to work around
323  // GStreamer inability to play .pls mediaItems
324  propExists = true;
325  try {
326  a = this.tempLib.getItemsByProperty(
327  SBProperties.customType, "radio_tempStreamList");
328  } catch (e) {
329  propExists = false;
330  }
331  if (propExists && a.length > 0) {
332  this.streamList = a.queryElementAt(0, Ci.sbIMediaList);
333  } else {
334  this.streamList = this.tempLib.createMediaList("simple");
335  this.streamList.setProperty(SBProperties.hidden, "1");
336  this.streamList.setProperty(SBProperties.isReadOnly, "1");
337  }
338 
339  // set custom types so we can easily find them later
340  this.favesList.setProperty(SBProperties.customType,
341  "radio_favouritesList");
342  this.streamList.setProperty(SBProperties.customType,
343  "radio_tempStreamList");
344  }
345 
346  // Seed the favouriteIDs array with the IDs of the stations
347  for (var i=0; i<this.favesList.length; i++) {
348  var item = this.favesList.getItemByIndex(i);
349  var id = item.getProperty(SC_id);
350  this.favouriteIDs.push(id);
351  }
352  },
353 
354  changeGenre : function(menulist) {
355  var deck = document.getElementById("loading-deck");
356  deck.selectedIndex = 0;
357 
358  var genre = menulist.selectedItem.value;
359  Application.prefs.setValue(shoutcastGenre, genre);
360  this.clearFilter();
361  setTimeout(function() {
362  RadioDirectory.loadTable(genre)
363  }, 100);
364  },
365 
366  loadTable : function(genre) {
367  // reset the library
368  this.radioLib.clear();
369 
370  // Make the progress meter spin
371  var el = songbirdMainWindow.document
372  .getElementById("sb-status-bar-status-progressmeter");
373  el.mode = "undetermined";
374 
375  // if genre is null, then we're just being asked to filter our existing
376  // data and we don't need to reload data
377  if (genre != null) {
378  var stationList = ShoutcastRadio.getStationList(genre);
379 
380  var count=0;
381  var minBR = Application.prefs.getValue(shoutcastMinBitRate, 64);
382  var minLC = Application.prefs.getValue(shoutcastMinListeners, 10);
383  var checkBitRate =
384  Application.prefs.getValue(shoutcastCheckBitRate, false);
385  var checkListeners =
386  Application.prefs.getValue(shoutcastCheckListeners, false);
387 
388  var trackArray = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
389  .createInstance(Ci.nsIMutableArray);
390  var propertiesArray = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
391  .createInstance(Ci.nsIMutableArray);
392  for (var i=0; i<stationList.length; i++) {
393  var station = stationList[i];
394  var name = station.name;
395  var id = station.id;
396  var bitrate = parseInt(station.bitrate);
397  var currentTrack = station.currentTrack;
398  var numListeners = station.numListeners;
399  var genres = station.genre;
400 
401  // Only list stations with listeners set above the preference
402  if (checkListeners && numListeners < minLC)
403  continue;
404 
405  // Only list stations with bitrates higher than the preference
406  if (checkBitRate && bitrate < minBR)
407  continue;
408 
409  var props = Cc[
410  "@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
411  .createInstance(Ci.sbIMutablePropertyArray);
412 
413  var heartSrc;
414  if (RadioDirectory.favouriteIDs.indexOf(id) != -1) {
415  heartSrc = "chrome://shoutcast-radio/skin/heart-active.png";
416  } else {
417  heartSrc = "chrome://shoutcast-radio/skin/invis-16x16.png";
418  }
419  props.appendProperty(SC_streamName, name);
420  props.appendProperty(SBProperties.bitRate, bitrate);
421  props.appendProperty(SBProperties.genre, genres);
422  props.appendProperty(SBProperties.comment, currentTrack);
423  props.appendProperty(SBProperties.contentType, "audio");
424  props.appendProperty(SC_listenerCount, numListeners);
425  props.appendProperty(SC_id, parseInt(id));
426  props.appendProperty(SC_bookmark, heartSrc);
427  propertiesArray.appendElement(props, false);
428 
429  trackArray.appendElement(
430  ioService.newURI(ShoutcastRadio.getListenURL(id), null, null),
431  false);
432  }
433 
434  // Go through favourite stations and add any custom stations
435  var customProps = Cc[
436  "@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
437  .createInstance(Ci.sbIMutablePropertyArray);
438  customProps.appendProperty(SC_id, -1);
439  dump("Looking for custom stations in genre: " + genre + "\n");
440  customProps.appendProperty(SBProperties.genre, genre);
441 
442  try {
443  var customStations =
444  RadioDirectory.favesList.getItemsByProperties(customProps);
445  dump("Custom stations found: " + customStations.length + "\n");
446  for (var i=0; i<customStations.length; i++) {
447  var station = customStations.queryElementAt(i,
448  Ci.sbIMediaItem);
449  station.setProperty(SC_bookmark,
450  "chrome://shoutcast-radio/skin/heart-active.png");
451 
452  station.setProperty(SBProperties.storageGUID,
453  station.guid);
454  var url = station.getProperty(SBProperties.contentURL);
455  var props = station.getProperties();
456  propertiesArray.appendElement(props, false);
457  trackArray.appendElement(
458  ioService.newURI(url, null, null), false);
459  }
460  } catch (e) {
461  // need to catch in case there are no custom stations
462  if (e.result != Components.results.NS_ERROR_NOT_AVAILABLE)
463  dump("exception: " + e + "\n");
464  }
465 
466  RadioDirectory.radioLib.batchCreateMediaItemsAsync(libListener,
467  trackArray, propertiesArray, false);
468 
469  var deck = document.getElementById("loading-deck");
470  deck.selectedIndex = 1;
471  }
472  },
473 
474  inputFilter : function(event) {
475  //do this now rather than doing it at every comparison
476  var value = event.target.value.toLowerCase();
477  if (value == "") {
478  this.clearFilter();
479  return;
480  }
481  this.setFilter(value);
482  },
483 
484  setFilter : function(value) {
485  document.getElementById("clearFilter").disabled = value.length == 0;
486  var srch = LibraryUtils.createConstraint([[["*",[value]]]]);
487  var view = this.playlist.getListView();
488  view.searchConstraint = srch;
489  Application.prefs.setValue("extensions.shoutcast-radio.filter", value);
490  },
491 
492  clearFilter : function() {
493  document.getElementById("clearFilter").disabled = true;
494  document.getElementById("filter").value = "";
495  this.playlist.getListView().searchConstraint = null;
496  Application.prefs.setValue("extensions.shoutcast-radio.filter", "");
497  },
498 
499  addStation : function() {
500  var retVals = {
501  name : null,
502  url : null,
503  genre : null
504  };
505 
506  var dialog = openDialog(
507  "chrome://shoutcast-radio/content/addFavourite.xul",
508  "add-station", "chrome,modal", retVals);
509 
510  dump("name: " + retVals.name + "\n");
511  dump("url: " + retVals.url + "\n");
512  dump("genre: " + retVals.genre + "\n");
513  if (retVals.name && retVals.url && retVals.genre) {
514  // Add to favourites
515  var props = Cc[
516  "@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
517  .createInstance(Ci.sbIMutablePropertyArray);
518  props.appendProperty(SC_streamName, retVals.name);
519  props.appendProperty(SBProperties.bitRate, 0);
520  props.appendProperty(SBProperties.genre, retVals.genre);
521  props.appendProperty(SBProperties.contentType, "audio");
522  //props.appendProperty(SBProperties.comment, "Not available");
523  //props.appendProperty(SC_listenerCount, 0);
524  props.appendProperty(SC_id, -1);
525  props.appendProperty(SC_bookmark,
526  "chrome://shoutcast-radio/skin/heart-active.png");
527  var uri = ioService.newURI(retVals.url, null, null);
528  var item = this.radioLib.createMediaItem(uri, props);
529  RadioDirectory.favesList.add(item);
530 #ifdef METRICS_ENABLED
531  gMetrics.metricsInc("shoutcast", "custom", "added");
532 #endif
533  }
534  }
535 }
536 
537 function createLibrary(databaseGuid, databaseLocation, init) {
538  if (typeof(init) == "undefined")
539  init = true;
540 
541  var directory;
542  if (databaseLocation) {
543  directory = databaseLocation.QueryInterface(Ci.nsIFileURL).file;
544  }
545  else {
546  directory = Cc["@mozilla.org/file/directory_service;1"].
547  getService(Ci.nsIProperties).
548  get("ProfD", Ci.nsIFile);
549  directory.append("db");
550  }
551 
552  var file = directory.clone();
553  file.append(databaseGuid + ".db");
554  var libraryFactory =
555  Cc["@songbirdnest.com/Songbird/Library/LocalDatabase/LibraryFactory;1"]
556  .getService(Ci.sbILibraryFactory);
557  var hashBag = Cc["@mozilla.org/hash-property-bag;1"].
558  createInstance(Ci.nsIWritablePropertyBag2);
559  hashBag.setPropertyAsInterface("databaseFile", file);
560  var library = libraryFactory.createLibrary(hashBag);
561  try {
562  if (init) {
563  library.clear();
564  }
565  }
566  catch(e) {
567  }
568 
569  if (init) {
570  loadData(databaseGuid, databaseLocation);
571  }
572  return library;
573 }
574 
575 var libListener = {
576  onProgress: function(i) {},
577  onComplete: function(array, result) {
578  // Reset the progress meter
579  var el = songbirdMainWindow.document
580  .getElementById("sb-status-bar-status-progressmeter");
581  el.mode = "";
582  SBDataSetStringValue("faceplate.status.text",
583  array.length + " " +
584  RadioDirectory._strings.getString("stationsFound"));
585  }
586 }
587 
588 function onPlaylistCellClick(e) {
589  if (e.getData("property") == SC_bookmark) {
590  var item = e.getData("item");
591 
592  var id = item.getProperty(SC_id);
593  var idx = RadioDirectory.favouriteIDs.indexOf(id);
594 
595  if (id == -1) {
596  // the "item" in the favourite list is different from the item
597  // in the radiolib
598  var faveGuid = item.getProperty(SBProperties.storageGUID);
599 
600 #ifdef METRICS_ENABLED
601  // it's a custom entered favourite list
602  gMetrics.metricsInc("shoutcast", "custom", "removed");
603 #endif
604  RadioDirectory.radioLib.remove(item);
605 
606  var faveItem = RadioDirectory.favesList.getItemByGuid(faveGuid);
607  RadioDirectory.favesList.remove(faveItem);
608  return;
609  }
610  if (idx != -1) {
611 #ifdef METRICS_ENABLED
612  // # of times a station is unfavourited
613  gMetrics.metricsInc("shoutcast", "favourites", "removed");
614 #endif
615 
616  // Already in the favourites list, so remove it
617  RadioDirectory.favouriteIDs.splice(idx, 1);
618  item.setProperty(SC_bookmark,
619  "chrome://shoutcast-radio/skin/invis-16x16.png");
620  var tree = document.getElementById("sb-playlist-tree");
621  tree.treeBoxObject.clearStyleAndImageCaches();
622  tree.treeBoxObject.invalidate();
623  for (var i=0; i<RadioDirectory.favesList.length; i++) {
624  var item = RadioDirectory.favesList.getItemByIndex(i);
625  var thatId = item.getProperty(SC_id);
626  if (thatId == id)
627  RadioDirectory.favesList.remove(item);
628  }
629  } else {
630 #ifdef METRICS_ENABLED
631  // # of times a station is favourited
632  gMetrics.metricsInc("shoutcast", "favourites", "added");
633 #endif
634 
635  // Add to favourites
636  var genreLabel =
637  document.getElementById('shoutcast-genre-menulist').label;
638  var genreValue =
639  document.getElementById('shoutcast-genre-menulist').value;
640  if (genreValue != "sbITop")
641  item.setProperty(SBProperties.genre, genreLabel);
642  RadioDirectory.favouriteIDs.push(id);
643  item.setProperty(SC_bookmark,
644  "chrome://shoutcast-radio/skin/heart-active.png");
645  RadioDirectory.favesList.add(item);
646  }
647 
648  // Add favorites node if necessary
649  Utils.ensureFavouritesNode();
650  }
651 }
652 
653 function onPlay(e) {
654  var item = RadioDirectory.playlist.mediaListView.selection.currentMediaItem;
655  var id = item.getProperty(SC_id);
656  var plsURL = ShoutcastRadio.getListenURL(id);
657  var plsMgr = Cc["@songbirdnest.com/Songbird/PlaylistReaderManager;1"]
658  .getService(Ci.sbIPlaylistReaderManager);
659  var listener = Cc["@songbirdnest.com/Songbird/PlaylistReaderListener;1"]
660  .createInstance(Ci.sbIPlaylistReaderListener);
661  var ioService = Cc["@mozilla.org/network/io-service;1"]
662  .getService(Ci.nsIIOService);
663 
664  // clear the current list of any existing streams, etc.
665  RadioDirectory.streamList.clear();
666 
667  listener.playWhenLoaded = true;
668  listener.observer = {
669  observe: function(aSubject, aTopic, aData) {
670  if (aTopic == "success") {
671  var list = aSubject;
672  var name = item.getProperty(SC_streamName);
673  for (var i=0; i<list.length; i++) {
674  var listItem = list.getItemByIndex(i);
675  listItem.setProperty(SC_streamName, name);
676  listItem.setProperty(SC_id, id);
677  listItem.setProperty(SBProperties.outerGUID, item.guid);
678  }
679  } else {
680  alert("Failed to load " + item.getProperty(SC_streamName) +
681  "\n");
682  }
683  }
684  }
685 
686 #ifdef METRICS_ENABLED
687  // # of times a station is played
688  gMetrics.metricsInc("shoutcast", "station", "total.played");
689 
690  // # of times this station (ID) is played
691  gMetrics.metricsInc("shoutcast", "station", "played." + id.toString());
692 
693  // # of times this genre is played
694  var genre = item.getProperty(SBProperties.genre);
695  gMetrics.metricsInc("shoutcast", "genre", "played." + genre);
696 #endif
697 
698  if (id == -1) {
699  plsURL = item.getProperty(SBProperties.contentURL);
700  }
701  var uri = ioService.newURI(plsURL, null, null);
702  plsMgr.loadPlaylist(uri, RadioDirectory.streamList, null, false, listener);
703 
704  e.stopPropagation();
705  e.preventDefault();
706 }
const Cu
function loadData(databaseGuid, databaseLocation)
const Cc
const shoutcastCheckListeners
Definition: directory.js:37
const shoutcastCheckBitRate
Definition: directory.js:36
var Application
Definition: sbAboutDRM.js:37
const shoutcastLibraryGuid
Definition: directory.js:31
inArray array
const shoutcastGenre
Definition: directory.js:33
function onComplete(job)
Definition: test_bug7406.js:85
const shoutcastMinBitRate
Definition: directory.js:34
var event
const SC_bitRate
const SC_listenerCount
const shoutcastMinListeners
Definition: directory.js:35
sidebarFactory createInstance
Definition: nsSidebar.js:351
var ioService
const shoutcastPlaylistInit
Definition: directory.js:32
const SC_bookmark
getService(Ci.sbIFaceplateManager)
const shoutcastTempLibGuid
Definition: directory.js:30
var strings
Definition: Info.js:46
_window init
Definition: FeedWriter.js:1144
this _contentSandbox label
Definition: FeedWriter.js:814
var count
Definition: test_bug7406.js:32
var dialog
Definition: openLocation.js:43
var libraryManager
aWindow setTimeout(function(){_this.restoreHistory(aWindow, aTabs, aTabData, aIdMap);}, 0)
ConcertTicketing unload
Definition: browse.js:54
const defaultGenre
Definition: directory.js:38
return null
Definition: FeedWriter.js:1143
function createLibrary(databaseGuid, databaseLocation)
Definition: test_load.js:151
const SC_id
var uri
Definition: FeedWriter.js:1135
function url(spec)
countRef value
Definition: FeedWriter.js:1423
const SC_comment
const Ci
Javascript wrappers for common library tasks.
function SBDataSetStringValue(aKey, aStringValue)
Set a string value. Changes the value of the data remote to the boolean passed in, regardless of its value before.
_getSelectedPageStyle s i
const SC_streamName
Selectors Utils
_updateTextAndScrollDataForFrame aData
var file
sbDeviceFirmwareAutoCheckForUpdate prototype observe