diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/applet.js b/sound150@claudiux/files/sound150@claudiux/6.4/applet.js
new file mode 100644
index 00000000000..37758abf343
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/applet.js
@@ -0,0 +1,3247 @@
+//"use strict";
+const Applet = imports.ui.applet;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Gio = imports.gi.Gio;
+const Interfaces = imports.misc.interfaces;
+const Util = imports.misc.util;
+const Cinnamon = imports.gi.Cinnamon;
+const Clutter = imports.gi.Clutter;
+const St = imports.gi.St;
+const PopupMenu = imports.ui.popupMenu;
+const GLib = imports.gi.GLib;
+const Cogl = imports.gi.Cogl; //Cogl
+const Gdk = imports.gi.Gdk;
+const Gtk = imports.gi.Gtk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const Cvc = imports.gi.Cvc;
+const Tooltips = imports.ui.tooltips;
+const Main = imports.ui.main;
+const Settings = imports.ui.settings;
+const Slider = imports.ui.slider;
+const Gettext = imports.gettext; // Needed for translations
+const Extension = imports.ui.extension; // Needed to reload this applet
+const Pango = imports.gi.Pango;
+const ModalDialog = imports.ui.modalDialog;
+
+let HtmlEncodeDecode = require("./lib/htmlEncodeDecode");
+const { xml2json } = require("lib/xml2json.min");
+
+
+const UUID = "sound150@claudiux";
+const HOME_DIR = GLib.get_home_dir();
+const PATH2SCRIPTS = HOME_DIR+"/.local/share/cinnamon/applets/"+UUID+"/scripts";
+
+const MEDIA_PLAYER_2_PATH = "/org/mpris/MediaPlayer2";
+const MEDIA_PLAYER_2_NAME = "org.mpris.MediaPlayer2";
+const MEDIA_PLAYER_2_PLAYER_NAME = "org.mpris.MediaPlayer2.Player";
+
+const ENABLED_APPLETS_KEY = "enabled-applets";
+// /org/cinnamon/show-media-keys-osd
+const SHOW_MEDIA_KEYS_OSD_KEY = "show-media-keys-osd";
+
+const RUNTIME_DIR = GLib.get_user_runtime_dir();
+const R30MPVSOCKET = RUNTIME_DIR + "/mpvradiosocket";
+
+// how long to show the output icon when volume is adjusted during media playback.
+const OUTPUT_ICON_SHOW_TIME_SECONDS = 3;
+
+function run_playerctld() {
+ Util.spawnCommandLineAsync("bash -C '"+ PATH2SCRIPTS +"/run_playerctld.sh'");
+}
+
+function kill_playerctld() {
+ Util.spawnCommandLineAsync("bash -C '"+ PATH2SCRIPTS +"/kill_playerctld.sh'");
+}
+
+
+
+/**
+ * DEBUG:
+ * Returns whether or not the DEBUG file is present in this applet directory ($ touch DEBUG)
+ * Used by the log function above.
+ */
+
+function DEBUG() {
+ let _debug = Gio.file_new_for_path(HOME_DIR + "/.local/share/cinnamon/applets/" + UUID + "/DEBUG");
+ return _debug.query_exists(null);
+};
+
+/**
+ * _:
+ * @str: string to try to translate.
+ * Try firstly with UUID domain, secondly with "cinnamon" domain, then with general domain.
+ */
+function _(str) {
+ let customTrans = Gettext.dgettext(UUID, str);
+ if (customTrans !== str && customTrans !== "")
+ return customTrans;
+ customTrans = Gettext.dgettext("cinnamon", str);
+ if (customTrans !== str && customTrans !== "")
+ return customTrans;
+ return Gettext.gettext(str);
+}
+
+// Logging
+function log(message, always = false) {
+ if (DEBUG() || always)
+ global.log("[" + UUID + "]: " + message);
+}
+
+function logDebug(message) {
+ log(message, true);
+}
+
+function logError(error) {
+ global.logError("[" + UUID + "]: " + error)
+}
+
+// To capitalize each word
+function capitalize_each_word(s) {
+ return s.toLowerCase().replace(/(^\w{1})|(\s+\w{1})/g, letter => letter.toUpperCase())
+}
+
+// Text wrapper
+const formatTextWrap = (text, maxLineLength) => {
+ const words = text.replace(/[\r\n]+/g, " ").split(" ");
+ let lineLength = 0;
+
+ // use functional reduce, instead of for loop
+ return words.reduce((result, word) => {
+ if (lineLength + word.length >= maxLineLength) {
+ lineLength = word.length;
+ return result + `\n${word}`; // don't add spaces upfront
+ } else {
+ lineLength += word.length + (result ? 1 : 0);
+ return result ? result + ` ${word}` : `${word}`; // add space only when needed
+ }
+ }, "");
+}
+/* global values */
+let players_without_seek_support = [
+ "telegram desktop", "totem",
+ "xplayer", "gnome-mplayer", "pithos",
+ "smplayer"];
+let players_with_seek_support = [
+ "clementine", "banshee", "rhythmbox",
+ "rhythmbox3", "pragha", "quodlibet",
+ "amarok", "xnoise", "gmusicbrowser",
+ "vlc", "qmmp", "deadbeef",
+ "audacious", "celluloid", "spotify", "mpv"];
+/* dummy vars for translation */
+let x = _("Playing");
+x = _("Paused");
+x = _("Stopped");
+
+let VOLUME_ADJUSTMENT_STEP = 0.02; /* Volume adjustment step in % */
+
+const ICON_SIZE = Math.trunc(28*global.ui_scale);
+
+const CINNAMON_DESKTOP_SOUNDS = "org.cinnamon.desktop.sound";
+const OVERAMPLIFICATION_KEY = "allow-amplified-volume";
+const VOLUME_SOUND_ENABLED_KEY = "volume-sound-enabled";
+const VOLUME_SOUND_FILE_KEY = "volume-sound-file";
+
+class ControlButton {
+ constructor(icon, tooltip, callback, small = false) {
+ this.destroyed = false;
+ this.actor = new St.Bin();
+
+ this.button = new St.Button();
+ this.button.connect("clicked", callback);
+
+ if (small) {
+ this.button.add_style_pseudo_class("small");
+ }
+
+ this.icon = new St.Icon({
+ icon_type: St.IconType.SYMBOLIC,
+ icon_name: icon,
+ style_class: (small) ? "popup-menu-icon" : ""
+ });
+ this.button.set_child(this.icon);
+ this.actor.add_actor(this.button);
+
+ this.tooltip = new Tooltips.Tooltip(this.button, tooltip);
+ }
+
+ getActor() {
+ if (this.destroyed) return null;
+ return this.actor;
+ }
+
+ setData(icon, tooltip) {
+ if (this.destroyed) return;
+ try {
+ if (this.icon) this.icon.icon_name = icon;
+ if (this.tooltip) this.tooltip.set_text(tooltip);
+ } catch(e) {}
+ }
+
+ setIconName(icon) {
+ if (this.destroyed) return;
+ try {
+ this.icon.icon_name = icon;
+ } catch(e) {}
+ }
+
+ setActive(status) {
+ if (this.destroyed) return;
+ try {
+ if (this.button) this.button.change_style_pseudo_class("active", status);
+ } catch(e) {}
+ }
+
+ setEnabled(status) {
+ if (this.destroyed) return;
+ try {
+ if (this.button) this.button.change_style_pseudo_class("insensitive", !status);
+ if (this.button) this.button.can_focus = status;
+ if (this.button) this.button.reactive = status;
+ } catch(e) {}
+ }
+
+ destroy() {
+ if (this.destroyed) return;
+ this.destroyed = true;
+ try {
+ this.tooltip.destroy();
+ this.actor.remove_actor(this.button);
+ this.button.remove_all_children();
+ this.button.destroy();
+ this.actor.destroy();
+ } catch(e) {}
+ finally {
+ this.tooltip = null;
+ this.button = null;
+ this.actor = null;
+ }
+ }
+}
+
+class VolumeSlider extends PopupMenu.PopupSliderMenuItem {
+ constructor(applet, stream, tooltip, app_icon) {
+ const startLevel = (tooltip == _("Microphone")) ? 1*applet.mic_level.slice(0, -1) : 1*applet.volume.slice(0, -1);
+ applet.showOSD = applet.showOSDonStartup;
+ super(startLevel);
+ this.applet = applet;
+ this.oldValue = startLevel;
+
+ Gtk.IconTheme.get_default().append_search_path("./icons");
+
+ if (tooltip)
+ this.tooltipText = tooltip + ": ";
+ else
+ this.tooltipText = "";
+
+ this.tooltip = new Tooltips.Tooltip(this.actor, this.tooltipText);
+
+ this.connect("value-changed", () => this._onValueChanged());
+
+ this.app_icon = app_icon;
+ if (this.app_icon == null) {
+ this.iconName = this.isMic ? "microphone-sensitivity-muted" : "audio-volume-muted";
+ this.icon = new St.Icon({
+ icon_name: this.iconName,
+ icon_type: St.IconType.SYMBOLIC,
+ icon_size: Math.trunc(16*global.ui_scale)}
+ );
+ }
+ else {
+ this.icon = new St.Icon({
+ icon_name: this.app_icon,
+ icon_type: St.IconType.FULLCOLOR,
+ icon_size: Math.trunc(16*global.ui_scale)
+ });
+ }
+
+ this.button = new ControlButton(
+ (this.iconName) ? this.iconName : this.app_icon,
+ _("Mute"),
+ () => {
+ let muted = false;
+ if (this._value) this.oldValue = this._value;
+ if (this.isMic) {
+ this.applet.mute_in_switch.setToggleState(!this.applet.mute_in_switch.state);
+ if (this.applet.mute_in_switch.state) muted = true;
+ } else {
+ this.applet.mute_out_switch.setToggleState(!this.applet.mute_out_switch.state);
+ if (this.applet.mute_out_switch.state) muted = true;
+ }
+ if (muted) {
+ this.oldValue = this._value;
+ this.setValue(0);
+ } else {
+ this.setValue(this.oldValue);
+ }
+ this._onValueChanged();
+ },
+ true
+ );
+
+ this.removeActor(this._slider);
+ //this.addActor(this.icon, {span: 0});
+ this.addActor(this.button.actor, {span: 0});
+ this.addActor(this._slider, {span: -1, expand: true});
+
+ this.connectWithStream(stream);
+ }
+
+ connectWithStream(stream) {
+ if (!stream) {
+ this.actor.hide();
+ this.stream = null;
+ } else {
+ this.actor.show();
+ this.stream = stream;
+ this.isMic = stream instanceof Cvc.MixerSource || stream instanceof Cvc.MixerSourceOutput;
+ this.isOutputSink = stream instanceof Cvc.MixerSink;
+
+ let mutedId = stream.connect("notify::is-muted", () => this._update());
+ let volumeId = stream.connect("notify::volume", () => this._update());
+ this.connect("destroy", () => {
+ stream.disconnect(mutedId);
+ stream.disconnect(volumeId);
+ });
+ }
+
+ this._update();
+ }
+
+ _onValueChanged() {
+ if (!this.stream) return;
+
+ let muted;
+ // Use the scaled volume max only for the main output
+ let volume = this._value * (this.isOutputSink ? this.applet._volumeMax : this.applet._volumeNorm);
+
+ if (this._value < 0.005) {
+ volume = 0;
+ muted = true;
+ } else {
+ muted = false;
+ //100% is magnetic:
+ if (this.applet.magneticOn === true && volume != this.applet._volumeNorm && volume > this.applet._volumeNorm * (1 - VOLUME_ADJUSTMENT_STEP / 2) && volume < this.applet._volumeNorm * (1 + VOLUME_ADJUSTMENT_STEP / 2))
+ volume = this.applet._volumeNorm;
+ //Other 25% magnetized?
+ if (this.applet.magneticOn === true && this.applet.magnetic25On === true) {
+ for (let i = 0.25; i < 1.5; i+=0.25) {
+ if (i==1) continue;
+ if (volume != i*this.applet._volumeNorm && volume > this.applet._volumeNorm * (i - VOLUME_ADJUSTMENT_STEP / 2) && volume < this.applet._volumeNorm * (i + VOLUME_ADJUSTMENT_STEP / 2))
+ volume = i*this.applet._volumeNorm;
+ }
+ }
+ }
+ this.stream.volume = volume;
+ this.stream.push_volume();
+
+ let icon = Gio.Icon.new_for_string(this._volumeToIcon(this._value));
+
+ if (this.applet.showOSD) {
+ Main.osdWindowManager.show(-1, icon, Math.round(volume/this.applet._volumeNorm * 100), null);
+ }
+
+
+ if (this.stream.is_muted !== muted)
+ this.stream.change_is_muted(muted);
+
+ if (!this._dragging)
+ this.applet._notifyVolumeChange(this.stream);
+ }
+
+ _onScrollEvent(actor, event) {
+ let direction = event.get_scroll_direction();
+
+ if (direction == Clutter.ScrollDirection.DOWN) {
+ this._value = Math.max(0, this._value - VOLUME_ADJUSTMENT_STEP / this.applet._volumeMax * this.applet._volumeNorm);
+ }
+ else if (direction == Clutter.ScrollDirection.UP) {
+ this._value = Math.min(1, this._value + VOLUME_ADJUSTMENT_STEP / this.applet._volumeMax * this.applet._volumeNorm);
+ }
+
+ this._slider.queue_repaint();
+ this.tooltip.show();
+ this.emit("value-changed", this._value);
+ }
+
+ _onKeyPressEvent(actor, event) {
+ let key = event.get_key_symbol();
+ if (key == Clutter.KEY_Right ||
+ key == Clutter.KEY_Left ||
+ key == Clutter.KEY_AudioRaiseVolume ||
+ key == Clutter.KEY_AudioLowerVolume) {
+ let delta = (key == Clutter.KEY_Right || key == Clutter.KEY_AudioRaiseVolume) ? VOLUME_ADJUSTMENT_STEP : -VOLUME_ADJUSTMENT_STEP;
+
+ if (delta < 0) {
+ this._value = Math.max(0, this._value + delta / this.applet._volumeMax * this.applet._volumeNorm);
+ } else {
+ this._value = Math.min(1, this._value + delta / this.applet._volumeMax * this.applet._volumeNorm);
+ }
+ this._slider.queue_repaint();
+ this.emit("value-changed", this._value);
+ this.emit("drag-end");
+ return true;
+ }
+ return false;
+ }
+
+
+ _update() {
+ // value: percentage of volume_max (set as value in the widget)
+ // visible_value: percentage of volume_norm (shown to the user)
+ // these only differ for the output, and only when the user changes the maximum volume
+ let volume = (!this.stream || this.stream.is_muted) ? 0 : this.stream.volume;
+ let value, visible_value, delta = VOLUME_ADJUSTMENT_STEP * this.applet._volumeMax / this.applet._volumeNorm;
+
+ if (this.isOutputSink) {
+ value = volume / this.applet._volumeMax;
+ visible_value = volume / this.applet._volumeNorm;
+ if (this.applet.magneticOn === true && visible_value != 1 && visible_value > 1 - delta / 2 && visible_value < 1 + delta / 2) {
+ visible_value = 1; // 100% is magnetic
+ value = this.applet._volumeNorm / this.applet._volumeMax;
+ this.applet._output.volume = this.applet._volumeNorm;
+ this.applet._output.push_volume();
+ }
+ if (this.applet.magneticOn === true && this.applet.magnetic25On === true) {
+ for (let i = 0.25; i < 1.5; i+=0.25) {
+ if (i==1) continue;
+ if (visible_value != i*this.applet._volumeNorm && visible_value > this.applet._volumeNorm * (i - VOLUME_ADJUSTMENT_STEP / 2) && visible_value < this.applet._volumeNorm * (i + VOLUME_ADJUSTMENT_STEP / 2)) {
+ visible_value = i*this.applet._volumeNorm;
+ value = visible_value / this.applet._volumeMax;
+ this.applet._output.volume = i*this.applet._volumeNorm;
+ this.applet._output.push_volume();
+ }
+ }
+
+ }
+ } else {
+ visible_value = volume / this.applet._volumeNorm;
+ value = visible_value
+ }
+
+ let percentage = Math.round(visible_value * 100) + "%";
+
+ this.tooltip.set_text(this.tooltipText + percentage);
+ if (this._dragging)
+ this.tooltip.show();
+ const iconName = this._volumeToIcon(value);
+ const iconNameWithoutMic = iconName.replace("-with-mic-disabled", "").replace("-with-mic-enabled", "");
+ if (this.app_icon == null) {
+ this.icon.icon_name = iconNameWithoutMic;
+ this.button.setIconName(iconNameWithoutMic);
+ if (this.isOutputSink)
+ this.applet.set_applet_icon_symbolic_name(iconName);
+ }
+ this.setValue(value);
+ if (this.isOutputSink) {
+ this.button.icon.style_class = "popup-menu-icon";
+ this.button.icon.style = (visible_value > 1) ? this.applet.actor.style : null;
+ }
+
+ // send data to applet
+ this.emit("values-changed", iconName, percentage);
+ }
+
+ _volumeToIcon(value) {
+ let nominal = this.applet._volumeNorm / this.applet._volumeMax;
+ let icon;
+ if (value < 0.005) {
+ icon = "muted";
+ } else {
+ let n2 = Math.floor(300 * value)/100;
+ if (this.isMic) {
+ if (n2 < 1)
+ icon = "low";
+ else if (n2 < 2)
+ icon = "medium";
+ else
+ icon = "high";
+ } else {
+ if (n2 < 1 * nominal)
+ icon = "low";
+ else if (n2 < 2 * nominal)
+ icon = "medium";
+ else if (n2 < 3 * nominal)
+ icon = "high";
+ else
+ icon = "overamplified";
+ }
+ }
+ if (this.applet.showMicMutedOnIcon && !this.isMic && (!this.applet.mute_in_switch || this.applet.mute_in_switch.state)) icon += "-with-mic-disabled";
+ else if (this.applet.showMicUnmutedOnIcon && !this.isMic && (this.applet.mute_in_switch && !this.applet.mute_in_switch.state)) icon += "-with-mic-enabled";
+
+ return this.isMic ? "microphone-sensitivity-" + icon + "-symbolic" : "audio-volume-" + icon + "-symbolic";
+ }
+}
+
+class Seeker extends Slider.Slider {
+ constructor(mediaServerPlayer, props, playerName) {
+ super(0, true);
+ this.actor.set_direction(St.TextDirection.LTR); // Do not invert on RTL layout
+ //~ this.actor.set_draw_value(true);
+ this.tooltipText = "00:00";
+ this.tooltip = new Tooltips.Tooltip(this.actor, this.tooltipText);
+
+ this.destroyed = false;
+ this.canSeek = true;
+ this.status = "Stopped";
+ this._wantedSeekValue = 0;
+
+ this._currentTime = 0;
+ this._length = 0;
+ this._trackid = "";
+
+ this._timeoutId = null;
+ this._timeoutId2 = null;
+ this._timerTicker = 0;
+
+ this._mediaServerPlayer = mediaServerPlayer;
+ this._prop = props;
+ this._playerName = playerName;
+
+ this.startingDate = Date.now();
+
+ this.seekerBox = new St.BoxLayout();
+
+ this.posLabel = new St.Label({text:" 00:00 "});
+ //~ logDebug("this.posLabel: "+this.posLabel);
+ //~ this.posLabel.clutterText.line_wrap = false;
+ //~ this.posLabel.clutterText.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
+ //~ this.posLabel.clutterText.ellipsize = Pango.EllipsizeMode.NONE;
+ this.durLabel = new St.Label({text:" 00:00 "});
+ //~ logDebug("this.durLabel: "+this.durLabel);
+ //~ this.durLabel.clutterText.line_wrap = false;
+ //~ this.durLabel.clutterText.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
+ //~ this.durLabel.clutterText.ellipsize = Pango.EllipsizeMode.NONE;
+
+ this.seekerBox.add_actor(this.posLabel);
+ this.seekerBox.add_actor(this.actor);
+ this.seekerBox.add_actor(this.durLabel);
+
+ this.connect("drag-end", () => {
+ if (this.destroyed) return;
+ this._setPosition();
+ });
+ this.connect("value-changed", () => {
+ if (this.destroyed) return;
+ if (!this._dragging) // Update on scroll events
+ this._setPosition();
+ });
+
+ this.actor.connect("enter-event", (event) => {
+ this.show_target_time()
+ //~ // let [x,y] = event.get_position();
+ //~ let [x,y] = this.tooltip.mousePosition;
+ //~ logDebug("enter-event - x: "+x);
+ //~ this.tooltipText = ""+x;
+ //~ this.tooltip.set_text(this.tooltipText);
+ //~ this.tooltip.show();
+ });
+
+ this.actor.connect("motion-event", (event) => {
+ this.show_target_time()
+ });
+
+ this.actor.connect("leave-event", (event) => {
+ let id = setTimeout( () => {
+ this.tooltip.hide();
+ clearTimeout(id);
+ }, 100);
+ });
+
+ this._seekChangedId = mediaServerPlayer.connectSignal("Seeked", (id, sender, value) => {
+ if (this.destroyed) return;
+ // Seek value sent by the player
+ if (value > 0) {
+ this._setPosition(value);
+ }
+ // Seek initiated by the position slider
+ else if (this._wantedSeekValue > 0) {
+ // Some broken gstreamer players (Banshee) reports always 0
+ // when the track is seeked so we set the position at the
+ // value we set on the slider
+ this._setPosition(this._wantedSeekValue);
+ }
+ else {
+ // Some players send negative values (Rhythmbox).
+ // Only positive values or zero are allowed.
+ this._setPosition(0);
+ }
+
+ this._wantedSeekValue = 0;
+ });
+
+ this._getCanSeek();
+ this._getPosition(); // Added
+ }
+
+ show_target_time() {
+ const [sliderX, sliderY] = this.actor.get_transformed_position();
+ const width = this.actor.width;
+ let [x,y] = this.tooltip.mousePosition;
+ this.tooltip.hide();
+ this.tooltipText = ""+this.time_for_label((x-sliderX)/width*this._length);
+ this.tooltip.set_text(this.tooltipText);
+ this.tooltip.visible = false;
+ this.tooltip.preventShow = false;
+ this.tooltip.show();
+ let id = setTimeout( () => {
+ this.tooltip.hide();
+ clearTimeout(id);
+ }, this.seekerTooltipDelay);
+ }
+
+ getActor() {
+ return this.seekerBox;
+ }
+
+ time_for_label(sec) {
+ //~ log("time_for_label("+sec+")", true);
+ let _sec = sec;
+ let _str = "";
+ let h = 0;
+ let m = 0;
+ let s = 0;
+ if (_sec > 3600) {
+ h = Math.floor(_sec / 3600);
+ _str = _str + h;
+ if (h < 10)
+ _str = "0" + _str;
+ _str += ":";
+ _sec = _sec - 3600 * h;
+ }
+ if (_sec > 60) {
+ m = Math.floor(_sec / 60);
+ if (m < 10)
+ _str = _str + "0" + m;
+ else
+ _str = _str + m;
+ _str += ":";
+ _sec = _sec - 60 * m
+ } else {
+ _str += "00:";
+ }
+ s = Math.round(_sec);
+ if (s < 10)
+ _str = _str + "0" + s;
+ else
+ _str = _str + s;
+
+ return " "+_str+" ";
+ }
+
+ play() {
+ if (this.destroyed) return;
+ run_playerctld();
+ this.status = "Playing";
+ this._getCanSeek();
+ }
+
+ pause() {
+ if (this.destroyed) return;
+ this.status = "Paused";
+ if (this.canSeek)
+ this._updateTimer();
+ else
+ this._updateValue();
+ if (this._timeoutId) {
+ try {Mainloop.source_remove(this._timeoutId);} catch(e) {}
+ this._timeoutId = null;
+ }
+ run_playerctld();
+ }
+
+ stop() {
+ if (this.destroyed) return;
+ this.status = "Stopped";
+ if (this.canSeek)
+ this._updateTimer();
+ else
+ this._updateValue();
+ if (this._timeoutId) {
+ try {Mainloop.source_remove(this._timeoutId);} catch(e) {}
+ this._timeoutId = null;
+ }
+ kill_playerctld(); //???
+ }
+
+ hideAll() {
+ if (this.destroyed) return;
+ if (this.durLabel) this.durLabel.hide();
+ if (this.actor) this.actor.hide();
+ if (this.posLabel) this.posLabel.hide();
+ if (this.seekerBox) this.seekerBox.hide();
+ //~ this.parent.hide();
+ }
+
+ showAll() {
+ if (this.destroyed) return;
+ if (this.seekerBox) this.seekerBox.show();
+ if (this.durLabel) this.durLabel.show();
+ if (this.posLabel) this.posLabel.show();
+ if (this.actor) this.actor.show();
+ //~ this.parent.show();
+ }
+
+ setTrack(trackid, length, force_zero=false) {
+ if (this.destroyed) return;
+ if (length > 0) {
+ this.showAll();
+ } else {
+ this.hideAll();
+ return
+ }
+ if (trackid != this._trackid || force_zero) {
+ this.startingDate = Date.now();
+ this._currentTime = 0;
+ this._trackid = trackid;
+ }
+ this._length = length;
+ if (this.status !== "Stopped" && this.durLabel) this.durLabel.set_text(this.time_for_label(length));
+ this._wantedSeekValue = 0;
+ this._updateValue();
+ }
+
+ _updateValue() {
+ if (this.destroyed) return GLib.SOURCE_REMOVE;
+ //~ this._currentTime = (Date.now() - this.startingDate) / 1000;
+
+ if (this.canSeek) {
+ this.showAll();
+ if (this._length > 0 && this._wantedSeekValue > 0) {
+ this._wantedSeekValue = this._wantedSeekValue / 1000000;
+ this.startingDate = Date.now() - this._wantedSeekValue * 1000;
+ this.setValue(this._wantedSeekValue / this._length);
+ this._currentTime = this._wantedSeekValue;
+ if (this.status === "Playing" && this.posLabel) this.posLabel.set_text(this.time_for_label(this._currentTime));
+ this._wantedSeekValue = 0;
+ } else if (!this._dragging) {
+ if (this._length > 0 && this._currentTime > 0) {
+ if (this.status === "Playing" && this.posLabel) this.posLabel.set_text(this.time_for_label(this._currentTime));
+ this.setValue(this._currentTime / this._length);
+ } else {
+ this.setValue(0);
+ if (this.status === "Playing" && this.posLabel) this.posLabel.set_text(" 00:00 ");
+ }
+ }
+ } else {
+ this._currentTime = (Date.now() - this.startingDate) / 1000;
+ if (this._length > 0) {
+ this.showAll();
+ if (this._wantedSeekValue > 0) {
+ this._wantedSeekValue = this._wantedSeekValue / 1000000;
+ this.startingDate = Date.now() - this._wantedSeekValue * 1000;
+ this.setValue(this._wantedSeekValue / this._length);
+ this._currentTime = this._wantedSeekValue;
+ if (this.status === "Playing" && this.posLabel) this.posLabel.set_text(this.time_for_label(this._currentTime));
+ this._wantedSeekValue = 0;
+ } else if (!this._dragging) {
+ if (this.status === "Playing" && this.posLabel) this.posLabel.set_text(this.time_for_label(this._currentTime));
+ this.setValue(this._currentTime / this._length);
+ if (this._timeoutId2) {
+ try {Mainloop.source_remove(this._timeoutId2);} catch(e) {}
+ this._timeoutId2 = null;
+ }
+ //~ this._timeoutId = Mainloop.timeout_add_seconds(1, this._updateValue.bind(this));
+ // Two lines removed:
+ this._timeoutId2 = Mainloop.timeout_add_seconds(1, this._timerCallback.bind(this));
+ return (this.status === "Playing") ? GLib.SOURCE_CONTINUE : GLib.SOURCE_REMOVE;
+ //Replaced by these two lines:
+ //~ if (this.status === "Playing")
+ //~ this._timeoutId = Mainloop.timeout_add_seconds(1, this._timerCallback.bind(this));
+ }
+ } else {
+ this.setValue(0);
+ if (this.status === "Playing" && this.posLabel) this.posLabel.set_text(" 00:00 ");
+ this.hideAll();
+ }
+ }
+ return GLib.SOURCE_REMOVE;
+ }
+
+ _timerCallback() {
+ if (this.destroyed) return GLib.SOURCE_REMOVE;
+ if (this.status === "Playing") {
+ if (this._timerTicker < 10) {
+ this._currentTime += 1;
+ this._timerTicker++;
+ this._updateValue();
+ } else { // Sync every 10 ticks
+ this._timerTicker = 0;
+ this._getPosition();
+ }
+ return GLib.SOURCE_CONTINUE;
+ } else if (this.status === "Stopped") {
+ this._setPosition(0);
+ this._timerTicker = 0;
+ this._currentTime = 0;
+ }
+ if (this._timeoutId) try {Mainloop.source_remove(this._timeoutId);} catch(e) {} // Added
+ this._timeoutId = null;
+ return GLib.SOURCE_REMOVE;
+ }
+
+ _updateTimer() {
+ if (this._timeoutId) {
+ try {Mainloop.source_remove(this._timeoutId);} catch(e) {}
+ this._timeoutId = null;
+ }
+
+ if (this.destroyed) return GLib.SOURCE_REMOVE;
+
+ if (this.status === "Playing") {
+ if (this.canSeek) {
+ this._getPosition();
+ this._timerTicker = 0;
+ //~ if (this._timeoutId) {
+ //~ Mainloop.source_remove(this._timeoutId);
+ //~ this._timeoutId = null;
+ //~ }
+ try {this._timeoutId = Mainloop.timeout_add_seconds(1, this._timerCallback.bind(this));} catch(e) {}
+ } else if (this._length > 0) {
+ this._getPosition();
+ this._timerTicker = 0;
+ //~ if (this._timeoutId) {
+ //~ Mainloop.source_remove(this._timeoutId);
+ //~ this._timeoutId = null;
+ //~ }
+ this._timeoutId = Mainloop.timeout_add_seconds(1, this._timerCallback.bind(this));
+ }
+ } else {
+ if (this.status === "Stopped") {
+ this._currentTime = 0;
+ //~ if (this._timeoutId) {
+ //~ Mainloop.source_remove(this._timeoutId);
+ //~ this._timeoutId = null;
+ //~ }
+ }
+ //this._updateValue();
+ }
+ }
+
+ _getCanSeek() {
+ // Some players say they "CanSeek" but don't actually give their position over dbus
+ if (players_without_seek_support.indexOf(this._playerName) > -1) {
+ this._setCanSeek(false);
+ return;
+ }
+
+ this._prop.GetRemote(MEDIA_PLAYER_2_PLAYER_NAME, "CanSeek", (position, error) => {
+ //~ logDebug("Dbus CanSeek: "+position[0].get_boolean());
+ //~ logDebug("Dbus !error: "+!error);
+ if (!error && position[0])
+ this._setCanSeek(position[0].get_boolean());
+ else
+ this._setCanSeek(false);
+ });
+ }
+
+ _cantSeek() {
+ this.canSeek = false;
+ if (this.destroyed) return;
+ if (this._length > 0) {
+ this.showAll();
+ this._updateValue();
+ } else {
+ this.hideAll();
+ }
+ }
+
+ _setCanSeek(seek) {
+ if (this.destroyed) return;
+
+ if (!this._mediaServerPlayer) {
+ this._cantSeek();
+ return
+ }
+ let playback_rate = this._mediaServerPlayer.Rate;
+ // Hide seek for non-standard speeds except: 0 may mean paused, Audacious returns null
+ if (seek && (playback_rate == 1.0 || !playback_rate)) {
+ this.canSeek = true;
+ this.showAll();
+ this._getPosition();
+ this._updateTimer();
+ } else {
+ this._cantSeek();
+ }
+ //~ logDebug("this.canSeek: "+this.canSeek);
+ }
+
+ _setPosition(value) {
+ if (this.destroyed) return;
+
+ if (value >= 0) {
+ this._currentTime = value / 1000000;
+ this._updateValue();
+ } else {
+ let time = this._value * this._length * 1000000;
+ this._wantedSeekValue = time;
+ if (this._mediaServerPlayer) this._mediaServerPlayer.SetPositionRemote(this._trackid, time);
+ }
+ }
+
+ _getPosition() {
+ if (this.destroyed) return;
+
+ this._prop.GetRemote(MEDIA_PLAYER_2_PLAYER_NAME, "Position", (position, error) => {
+ //~ logDebug("_getPosition dbus !error: "+!error);
+ if (!error && position[0]) {
+ //~ logDebug("_getPosition position: "+position[0].get_int64());
+ this._setPosition(position[0].get_int64());
+ } else {
+ let pos;
+ try {
+ pos = position[0].get_int64();
+ } catch(e) {
+ pos = "NaN";
+ //~ logError("pos error: "+e);
+ }
+ if (isNaN(pos)) {
+ //~ logDebug("pos is NaN!!!");
+ this._currentTime = (Date.now() - this.startingDate) / 1000;
+ //~ logDebug("this._currentTime: "+this._currentTime);
+ this._setPosition(this._currentTime * 1000000);
+ } else {
+ //~ logDebug("pos is Valid!!! pos:" + pos);
+ this._setPosition(pos);
+ }
+ }
+ });
+ }
+
+ destroy() {
+ this.destroyed = true;
+ if (this._timeoutId) {
+ try {Mainloop.source_remove(this._timeoutId);} catch(e) {}
+ this._timeoutId = null;
+ }
+ if (this._timeoutId2) {
+ try {Mainloop.source_remove(this._timeoutId2);} catch(e) {}
+ this._timeoutId2 = null;
+ }
+ if (this._seekChangedId) {
+ this._mediaServerPlayer.disconnectSignal(this._seekChangedId);
+ this._seekChangedId = null;
+ }
+
+ this.disconnectAll();
+
+ this.posLabel = null;
+ this.durLabel = null;
+ this.seekerBox = null;
+ this._mediaServerPlayer = null;
+ this._prop = null;
+ }
+}
+
+class StreamMenuSection extends PopupMenu.PopupMenuSection {
+ constructor(applet, stream) {
+ super();
+
+ let iconName = stream.icon_name;
+ let name = stream.name;
+
+ // capitalize the stream name
+ if (name.length > 2) {
+ name = name.charAt(0).toUpperCase() + name.slice(1);
+ }
+
+ // Trim stream name
+ //~ if (name.length > 20) {
+ //~ name = name.substring(0, 16) + "... ";
+ //~ }
+ name = formatTextWrap(name, 20);
+ //~ log("StreamMenuSection: name:"+name, true);
+
+ // Special cases
+ if (name === "Banshee") {
+ iconName = "banshee";
+ }
+ else if (name === "Spotify") {
+ iconName = "spotify";
+ }
+ else if (name === "VBox") {
+ name = "Virtualbox";
+ iconName = "virtualbox";
+ }
+ else if (name === "Firefox") {
+ iconName = "firefox";
+ }
+ else if (name === "Mpv") {
+ iconName = "mpv"
+ }
+ else if (iconName === "audio") {
+ iconName = "audio-x-generic";
+ }
+
+ if (name != "Muffin") { // This test is it really necessary?
+ this.slider = new VolumeSlider(applet, stream, name, iconName);
+ this.slider._slider.style = "min-width: 6em;";
+ //~ this.slider._slider.style = "width: 6em;";
+ this.addMenuItem(this.slider);
+ } else {
+ this.slider = null
+ }
+ }
+}
+
+class Player extends PopupMenu.PopupMenuSection {
+ constructor(applet, busname, owner) {
+ super();
+ this._owner = owner;
+ this._busName = busname;
+ this._applet = applet;
+ //~ logDebug("busname: "+busname);
+
+ // We'll update this later with a proper name
+ this._name = this._busName;
+
+ let asyncReadyCb = (proxy, error, property) => {
+ if (error)
+ log(error);
+ else {
+ this[property] = proxy;
+ this._dbus_acquired();
+ }
+ };
+
+ Interfaces.getDBusProxyWithOwnerAsync(MEDIA_PLAYER_2_NAME,
+ this._busName,
+ (p, e) => asyncReadyCb(p, e, "_mediaServer"));
+
+ Interfaces.getDBusProxyWithOwnerAsync(MEDIA_PLAYER_2_PLAYER_NAME,
+ this._busName,
+ (p, e) => asyncReadyCb(p, e, "_mediaServerPlayer"));
+
+ Interfaces.getDBusPropertiesAsync(this._busName,
+ MEDIA_PLAYER_2_PATH,
+ (p, e) => asyncReadyCb(p, e, "_prop"));
+
+ }
+
+ _dbus_acquired() {
+ if (!this._prop || !this._mediaServerPlayer || !this._mediaServer)
+ return;
+
+ if (this._mediaServer.Identity) {
+ this._name = this._mediaServer.Identity;
+ } else {
+ let displayName = this._busName.replace("org.mpris.MediaPlayer2.", "");
+ this._name = capitalize_each_word(displayName);
+ }
+
+ let mainBox = new PopupMenu.PopupMenuSection();
+ this.addMenuItem(mainBox);
+
+ this.vertBox = new St.BoxLayout({
+ style_class: "sound-player",
+ important: true,
+ vertical: true
+ });
+ mainBox.addActor(this.vertBox, { expand: false });
+
+ // Player info
+ this._playerBox = new St.BoxLayout();
+ this.playerIcon = new St.Icon({
+ icon_type: St.IconType.SYMBOLIC,
+ style_class: "popup-menu-icon"
+ });
+ this.playerLabel = new St.Label({
+ y_expand: true, y_align: Clutter.ActorAlign.CENTER,
+ x_expand: true, x_align: Clutter.ActorAlign.START
+ });
+
+ this._playerBox.add_actor(this.playerIcon);
+ this._playerBox.add_actor(this.playerLabel);
+
+ if (this._mediaServer.CanRaise) {
+ this._showCanRaise();
+ }
+ if (this._mediaServer.CanQuit) {
+ this._showCanQuit();
+ }
+
+ this.vertBox.add_actor(this._playerBox);
+
+ // Cover Box (art + track info)
+ this._trackCover = new St.Bin({x_align: St.Align.MIDDLE});
+ this._trackCoverFile = this._trackCoverFileTmp = false;
+ this._oldTrackCoverFile = false;
+ this.coverBox = new Clutter.Box();
+ let l = new Clutter.BinLayout({
+ x_align: Clutter.BinAlignment.FILL,
+ y_align: Clutter.BinAlignment.END
+ });
+ try {
+ this.coverBox.set_layout_manager(l);
+ } catch(e) {logError("Unable to set_layout_manager(l)!: "+e)}
+
+ // Cover art
+ this.cover = new St.Icon({
+ icon_name: "media-optical",
+ icon_size: Math.trunc(300*global.ui_scale),
+ //icon_type: St.IconType.FULLCOLOR
+ icon_type: St.IconType.SYMBOLIC
+ });
+ this.coverBox.add_actor(this.cover);
+
+ this._cover_load_handle = 0;
+ this._cover_path = null;
+
+ //~ this.display_cover_button = new ControlButton("image-x-generic",
+ //~ _("View cover"),
+ //~ () => {
+ //~ Util.spawnCommandLineAsync("xdg-open "+this._cover_path)
+ //~ },
+ //~ true
+ //~ );
+ //~ this.coverBox.add_actor(this.display_cover_button.getActor());
+ //~ this.display_cover_button.getActor().show();
+
+ // Track info (artist + title)
+ this._artist = _("Unknown Artist");
+ this._album = _("Unknown Album");
+ this._title = _("Unknown Title");
+ //this.trackInfo = new St.BoxLayout({style_class: "sound-player-overlay", style: "height: auto;", important: true, vertical: true});
+ // Removing "style: "height: auto;"" avoids warning messages "St-WARNING **: Ignoring length property that isn't a number at line 1, col 9"
+ this.trackInfo = new St.BoxLayout({
+ style_class: "sound-player-overlay",
+ //~ style: "min-height: 6em;", // replaces "height: auto;" REMOVED: DEPRECATED!
+ important: true,
+ vertical: true
+ });
+ let artistInfo = new St.BoxLayout();
+ let artistIcon = new St.Icon({
+ icon_type: St.IconType.SYMBOLIC,
+ icon_name: "system-users",
+ style_class: "popup-menu-icon"
+ });
+ this.artistLabel = new St.Label({text:this._artist});
+ this.artistLabel.clutterText.line_wrap = true;
+ this.artistLabel.clutterText.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
+ this.artistLabel.clutterText.ellipsize = Pango.EllipsizeMode.NONE;
+ artistInfo.add_actor(artistIcon);
+ artistInfo.add_actor(this.artistLabel);
+ let titleInfo = new St.BoxLayout();
+ let titleIcon = new St.Icon({ icon_type: St.IconType.SYMBOLIC, icon_name: "audio-x-generic", style_class: "popup-menu-icon" });
+ this.titleLabel = new St.Label({text:this._title});
+ this.titleLabel.clutterText.line_wrap = true;
+ this.titleLabel.clutterText.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
+ this.titleLabel.clutterText.ellipsize = Pango.EllipsizeMode.NONE;
+ titleInfo.add_actor(titleIcon);
+ titleInfo.add_actor(this.titleLabel);
+ //~ titleInfo.add_actor(this.display_cover_button.getActor());
+ this.trackInfo.add_actor(artistInfo);
+ this.trackInfo.add_actor(titleInfo);
+ //~ this.trackInfo.add_actor(this.display_cover_button.getActor());
+ this.coverBox.add_actor(this.trackInfo);
+
+ this._trackCover.set_child(this.coverBox);
+ try {
+ this.vertBox.add_actor(this._trackCover);
+ } catch(e) {logError("Unable to add actor this._trackCover to this.vertBox!: "+e)}
+
+ // Labels
+ //~ durationLabel = new St.Label({text:" 00:00 "});
+ //~ durationLabel.clutterText.line_wrap = false;
+ //~ durationLabel.clutterText.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
+ //~ durationLabel.clutterText.ellipsize = Pango.EllipsizeMode.NONE;
+ //~ positionLabel = new St.Label({text:" 00:00 "});
+ //~ positionLabel.clutterText.line_wrap = false;
+ //~ positionLabel.clutterText.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
+ //~ positionLabel.clutterText.ellipsize = Pango.EllipsizeMode.NONE;
+
+ // Playback controls
+ let trackControls = new St.Bin({x_align: St.Align.MIDDLE});
+ if (this._prevButton) this._prevButton.destroy();
+ this._prevButton = new ControlButton("media-skip-backward",
+ _("Previous"),
+ () => {
+ if (this._seeker) {
+ if (this._seeker.status === "Playing" && this._seeker.posLabel) this._seeker.posLabel.set_text(" 00:00 ");
+ this._seeker.startingDate = Date.now();
+ this._seeker._setPosition(0);
+ }
+
+ if (this._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Previous", "");
+ } else
+ this._mediaServerPlayer.PreviousRemote();
+ });
+ if (this._playButton) this._playButton.destroy();
+ this._playButton = new ControlButton("media-playback-start",
+ _("Play"),
+ () => this._mediaServerPlayer.PlayPauseRemote());
+ if (this._stopButton) this._stopButton.destroy();
+ this._stopButton = new ControlButton("media-playback-stop",
+ _("Stop"),
+ () => {
+ if (this._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Stop", "");
+ } else {
+ this._mediaServerPlayer.StopRemote()
+ }
+ });
+ if (this._nextButton) this._nextButton.destroy();
+ this._nextButton = new ControlButton("media-skip-forward",
+ _("Next"),
+ () => {
+ if (this._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Next", "");
+ } else
+ this._mediaServerPlayer.NextRemote();
+ });
+
+ try {
+ this.trackInfo.add_actor(trackControls);
+ } catch(e) {logError("Unable to add actor trackControls to this.trackInfo!")}
+
+ this.controls = new St.BoxLayout();
+ if (St.Widget.get_default_direction() === St.TextDirection.RTL)
+ this.controls.set_pack_start(true);
+
+ this.controls.add_actor(this._prevButton.getActor());
+ this.controls.add_actor(this._playButton.getActor());
+ this.controls.add_actor(this._stopButton.getActor());
+ this.controls.add_actor(this._nextButton.getActor());
+ trackControls.set_child(this.controls);
+
+ this._loopButton = new ControlButton("media-playlist-consecutive", _("Consecutive Playing"), () => this._toggleLoopStatus());
+ this.controls.add_actor(this._loopButton.getActor());
+
+ this._shuffleButton = new ControlButton("media-playlist-shuffle", _("No Shuffle"), () => this._toggleShuffle());
+ this.controls.add_actor(this._shuffleButton.getActor());
+
+
+ // Position slider
+ if (this._mediaServerPlayer) {
+ if (this._seeker) this._seeker.destroy();
+ this._seeker = new Seeker(
+ this._mediaServerPlayer,
+ this._prop,
+ this._name.toLowerCase()
+ );
+ this.vertBox.add_actor(this._seeker.getActor());
+ //this.vertBox.add_actor(seekerBox);
+ }
+
+
+ this._applet._updatePlayerMenuItems();
+
+ this._setStatus(this._mediaServerPlayer.PlaybackStatus);
+ this._setMetadata(this._mediaServerPlayer.Metadata);
+
+ this._propChangedId = this._prop.connectSignal("PropertiesChanged", (proxy, sender, [iface, props]) => {
+ try {
+ if (props.PlaybackStatus)
+ this._setStatus(props.PlaybackStatus.unpack());
+ if (props.Metadata)
+ this._setMetadata(props.Metadata.deep_unpack());
+ if (props.CanGoNext || props.CanGoPrevious)
+ this._updateControls();
+ //~ else {
+ //~ if(!props.CanGoNext) this._nextButton.setEnabled(false);
+ //~ if(!props.CanGoPrevious) this._prevButton.setEnabled(false);
+ //~ }
+ if (props.LoopStatus)
+ this._setLoopStatus(props.LoopStatus.unpack());
+ if (props.Shuffle)
+ this._setShuffle(props.Shuffle.unpack());
+ if (props.Identity) {
+ this._name = props.Identity.unpack();
+ this._applet._updatePlayerMenuItems();
+ }
+ if (props.CanRaise) {
+ this._showCanRaise();
+ }
+ if (props.CanQuit) {
+ this._showCanQuit();
+ }
+ if (props.DesktopEntry) {
+ this._applet.passDesktopEntry(props.DesktopEntry.unpack());
+ }
+ } catch(e) {}
+ });
+
+ this._setLoopStatus(this._mediaServerPlayer.LoopStatus);
+ this._setShuffle(this._mediaServerPlayer.Shuffle);
+
+ if (this._mediaServer.DesktopEntry) {
+ this._applet.passDesktopEntry(this._mediaServer.DesktopEntry);
+ }
+ }
+
+ _showCanRaise() {
+ let btn = new ControlButton("go-up", _("Open Player"), () => {
+ if (this._name.toLowerCase() === "spotify") {
+ // Spotify isn't able to raise via Dbus once its main UI is closed
+ Util.spawn(["spotify"]);
+ }
+ else {
+ this._mediaServer.RaiseRemote();
+ }
+ this._applet.menu.close();
+ }, true);
+ this._playerBox.add_actor(btn.actor);
+ }
+
+ _showCanQuit() {
+ let btn = new ControlButton("window-close", _("Quit Player"), () => {
+ if (this._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Stop", "");
+ } else
+ this._mediaServer.QuitRemote();
+ this._applet.menu.close();
+ }, true);
+ this._playerBox.add_actor(btn.actor);
+
+ // get the desktop entry and pass it to the applet
+ this._prop.GetRemote(MEDIA_PLAYER_2_NAME, "DesktopEntry", (result, error) => {
+ if (!error)
+ this._applet.passDesktopEntry(result[0].unpack());
+ });
+ }
+
+ _setName(status) {
+ this.playerLabel.set_text(this._name + " - " + _(status));
+ }
+
+ _updateControls() {
+ var canGoNext = false;
+ var canGoPrevious = false;
+ try {
+ this._prop.GetRemote(MEDIA_PLAYER_2_PLAYER_NAME, "CanGoNext", (value, error) => {
+ //~ logDebug("error: "+error);
+ if (!error) {
+ //~ logDebug("value[0].unpack(): "+value[0].unpack());
+ canGoNext = value[0].unpack();
+ //~ logDebug("canGoNext from value: "+canGoNext);
+ this._nextButton.setEnabled(canGoNext);
+ }
+ else {
+ canGoNext = false;
+ //~ this._nextButton.setEnabled(canGoNext);
+ }
+ });
+ } catch(e) {
+ canGoNext = false;
+ //~ this._nextButton.setEnabled(canGoNext);
+ }
+ try {
+ this._prop.GetRemote(MEDIA_PLAYER_2_PLAYER_NAME, "CanGoPrevious", (value, error) => {
+ if (!error) {
+ canGoPrevious = value[0].unpack();
+ this._prevButton.setEnabled(canGoPrevious);
+ }
+ else {
+ canGoPrevious = false;
+ //~ this._prevButton.setEnabled(canGoPrevious);
+ }
+ });
+ } catch(e) {
+ canGoPrevious = false;
+ //~ this._prevButton.setEnabled(canGoPrevious);
+ }
+ //~ logDebug("canGoNext: "+canGoNext);
+ //~ logDebug("canGoPrevious: "+canGoPrevious);
+ //~ this._nextButton.setEnabled(canGoNext);
+ //~ this._prevButton.setEnabled(canGoPrevious);
+ }
+
+ async _setMetadata(metadata) {
+ if (!metadata)
+ return;
+
+ //~ for (let info of Object.keys(metadata)) {
+ //~ log(""+info+": "+metadata[info].unpack(), true);
+ //~ }
+
+ let trackid = ""; // D-Bus path: A unique identity for this track
+ if (metadata["mpris:trackid"]) {
+ trackid = metadata["mpris:trackid"].unpack();
+ }
+
+ let trackLength = 0; // Track length in secs
+ if (metadata["mpris:length"]) {
+ trackLength = metadata["mpris:length"].unpack() / 1000000;
+ }
+ //this._seeker.setTrack(trackid, trackLength);
+
+ if (metadata["xesam:artist"]) {
+ switch (metadata["xesam:artist"].get_type_string()) {
+ case "s":
+ // smplayer sends a string
+ this._artist = metadata["xesam:artist"].unpack();
+ break;
+ case "as":
+ // others send an array of strings
+ this._artist = metadata["xesam:artist"].deep_unpack().join(", ");
+ break;
+ default:
+ this._artist = _("Unknown Artist");
+ }
+ // make sure artist isn't empty
+ if (!this._artist) this._artist = _("Unknown Artist");
+ }
+ else
+ this._artist = _("Unknown Artist");
+
+ this.artistLabel.set_text(this._artist);
+
+ if (metadata["xesam:album"])
+ this._album = metadata["xesam:album"].unpack();
+ else
+ this._album = _("Unknown Album");
+
+ let old_title = ""+this._title;
+ if (metadata["xesam:title"]) {
+ this._title = metadata["xesam:title"].unpack();
+ if (this._title.includes("xml")) {
+ let xml_string = this._title.replace(/>\s*<"); // deletes all useless spaces.
+
+ try {
+ xml_string = HtmlEncodeDecode.decode(xml_string);
+ let json_data = xml2json(xml_string);
+ //~ log("json_data: "+JSON.stringify(json_data, null, 4), true);
+ if (json_data["ZettaLite"]) {
+ //~ log("ZettaLite data!!!", true);
+ let json_title = ""+json_data["ZettaLite"]["LogEventCollection"]["LogEvent"][0]["Asset"]["Title"];
+ let json_artist = ""+json_data["ZettaLite"]["LogEventCollection"]["LogEvent"][0]["Asset"]["Artist1"];
+ //~ log("json_title: "+json_title, true);
+ //~ log("json_artist: "+json_artist, true);
+ if (json_title) {
+ this._title = capitalize_each_word(json_title);
+ } else {
+ this._title = _("Unknown Title");
+ }
+ if (json_artist) {
+ this._artist = capitalize_each_word(json_artist);
+ this.artistLabel.set_text(this._artist);
+ } else {
+ this._artist = _("Unknown Artist");
+ }
+ } else
+ this._title = _("Unknown Title");
+ } catch(e) {
+ //~ logError("XML error: "+e);
+ this._title = _("Unknown Title");
+ }
+ }
+ else if (this._title.includes(" - ") && this._artist == _("Unknown Artist")) {
+ [this._artist, this._title] = this._title.split(" - ");
+ this.artistLabel.set_text(this._artist);
+ }
+ } else {
+ this._title = _("Unknown Title");
+ }
+ this.titleLabel.set_text(this._title);
+ this._seeker.setTrack(trackid, trackLength, old_title != this._title);
+
+ let change = false;
+ if (metadata["mpris:artUrl"]) {
+ let artUrl = metadata["mpris:artUrl"].unpack();
+ if (this._trackCoverFile != artUrl) {
+ this._trackCoverFile = artUrl;
+ change = true;
+ }
+ } else if(metadata["xesam:url"]) {
+ await Util.spawnCommandLineAsyncIO("bash -C %s/get_album_art.sh".format(PATH2SCRIPTS), Lang.bind(this, function(stdout, stderr, exitCode) {
+ if (exitCode === 0) {
+ this._trackCoverFile = "file://"+stdout;
+ if (this._oldTrackCoverFile != this._trackCoverFile) {
+ this._oldTrackCoverFile = this._trackCoverFile;
+ let cover_path = decodeURIComponent(this._trackCoverFile);
+ cover_path = cover_path.replace("file://", "");
+ const file = Gio.File.new_for_path(cover_path);
+ try {
+ const fileInfo = file.query_info("standard::*,unix::uid",
+ Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
+ const size = fileInfo.get_size();
+ if (size > 0) {
+ this._showCover(cover_path);
+ } else {
+ cover_path = null;
+ }
+ } catch(e) {
+ cover_path = null;
+ this._trackCoverFile = null;
+ change = true;
+ }
+ }
+ } else {
+ this._trackCoverFile = null;
+ change = true;
+ }
+ }));
+ } else {
+ if (this._trackCoverFile != false) {
+ this._trackCoverFile = false;
+ change = true;
+ }
+ }
+
+ if (change) {
+ if (this._trackCoverFileTmp) {
+ this._trackCoverFileTmp.delete(null);
+ this._trackCoverFileTmp = null;
+ }
+ if (this._trackCoverFile) {
+ let cover_path = "";
+ if (this._trackCoverFile.match(/^http/)) {
+ if (!this._trackCoverFileTmp)
+ this._trackCoverFileTmp = Gio.file_new_tmp("XXXXXX.mediaplayer-cover")[0];
+ Util.spawn_async(["wget", this._trackCoverFile, "-O", this._trackCoverFileTmp.get_path()], () => this._onDownloadedCover());
+ }
+ else if (this._trackCoverFile.match(/data:image\/(png|jpeg);base64,/)) {
+ if (!this._trackCoverFileTmp)
+ this._trackCoverFileTmp = Gio.file_new_tmp("XXXXXX.mediaplayer-cover")[0];
+ const cover_base64 = this._trackCoverFile.split(",")[1];
+ const base64_decode = data => new Promise(resolve => resolve(GLib.base64_decode(data)));
+ if (!cover_base64) {
+ return;
+ }
+ base64_decode(cover_base64)
+ .then(decoded => {
+ this._trackCoverFileTmp.replace_contents(
+ decoded,
+ null,
+ false,
+ Gio.FileCreateFlags.REPLACE_DESTINATION,
+ null
+ );
+ return this._trackCoverFileTmp.get_path();
+ })
+ .then(path => this._showCover(path));
+ }
+ else {
+ cover_path = decodeURIComponent(this._trackCoverFile);
+ cover_path = cover_path.replace("file://", "");
+ this._showCover(cover_path);
+ }
+ }
+ else {
+ this._trackCoverFile = null;
+ this._trackCoverFileTmp = null;
+ this._showCover(null); //false
+ }
+ }
+ this._applet.setAppletTextIcon(this, true);
+ }
+
+ _setStatus(status) {
+ if (!status)
+ return;
+ this._playerStatus = status;
+ if (status == "Playing") {
+ this._playButton.setData("media-playback-pause", _("Pause"));
+ this.playerIcon.set_icon_name("media-playback-start");
+ this._applet.setAppletTextIcon(this, true);
+ this._seeker.play();
+ }
+ else if (status == "Paused") {
+ this._playButton.setData("media-playback-start", _("Play"));
+ this.playerIcon.set_icon_name("media-playback-pause");
+ this._applet.setAppletTextIcon(this, false);
+ this._seeker.pause();
+ }
+ else if (status == "Stopped") {
+ this._playButton.setData("media-playback-start", _("Play"));
+ this.playerIcon.set_icon_name("media-playback-stop");
+ this._applet.setAppletTextIcon(this, false);
+ this._seeker.stop();
+ } else {
+ this._applet.setAppletTextIcon(this, false);
+ }
+
+ this._setName(status);
+ }
+
+ _toggleLoopStatus() {
+ let mapping = {
+ "None": "Playlist",
+ "Playlist": "Track",
+ "Track": "None"
+ };
+
+ this._mediaServerPlayer.LoopStatus = mapping[this._mediaServerPlayer.LoopStatus];
+ this._setLoopStatus(this._mediaServerPlayer.LoopStatus);
+ }
+
+ _setLoopStatus(status) {
+ this._loopButton.actor.visible = this._applet.extendedPlayerControl && this._mediaServerPlayer.LoopStatus;
+
+ if (status === "None")
+ this._loopButton.setData("media-playlist-consecutive-symbolic", _("Consecutive Playing"));
+ else if (status === "Track")
+ this._loopButton.setData("media-playlist-repeat-song", _("Repeat Single"));
+ else if (status === "Playlist")
+ this._loopButton.setData("media-playlist-repeat", _("Repeat All"));
+
+ this._loopButton.setActive(status !== "None");
+ }
+
+ _toggleShuffle() {
+ this._mediaServerPlayer.Shuffle = !this._mediaServerPlayer.Shuffle;
+ }
+
+ _setShuffle(status) {
+ this._shuffleButton.actor.visible = this._applet.extendedPlayerControl && this._mediaServerPlayer.Shuffle;
+
+ this._shuffleButton.setData("media-playlist-shuffle", status ? _("Shuffle") : _("No Shuffle"));
+ this._shuffleButton.setActive(status);
+ }
+
+ _onDownloadedCover() {
+ if (!this._trackCoverFileTmp) return;
+ let cover_path = this._trackCoverFileTmp.get_path();
+ this._showCover(cover_path);
+ }
+
+ _showCover(cover_path) {
+ if (! cover_path || ! GLib.file_test(cover_path, GLib.FileTest.EXISTS)) {
+ this.cover = new St.Icon({
+ style_class: "sound-player-generic-coverart",
+ important: true,
+ icon_name: "media-optical",
+ icon_size: Math.trunc(300*global.ui_scale),
+ //icon_type: St.IconType.FULLCOLOR
+ icon_type: St.IconType.SYMBOLIC
+ });
+ cover_path = null;
+ }
+ else {
+ this._cover_path = cover_path;
+ this._applet._icon_path = cover_path; // Added
+ this._applet.setAppletIcon(this._applet.player, cover_path); // Added
+ this._cover_load_handle = St.TextureCache.get_default().load_image_from_file_async(
+ cover_path,
+ Math.trunc(300*global.ui_scale),
+ Math.trunc(300*global.ui_scale),
+ this._on_cover_loaded.bind(this)
+ );
+ this._applet.setIcon();
+
+
+ //~ log("this._cover_path: "+this._cover_path, true);
+ try {
+ let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
+ this._cover_path,
+ Math.trunc(300*global.ui_scale),
+ Math.trunc(300*global.ui_scale)
+ );
+ if (pixbuf) {
+ let image = new Clutter.Image();
+ image.set_data(
+ pixbuf.get_pixels(),
+ pixbuf.get_has_alpha() ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888,
+ pixbuf.get_width(),
+ pixbuf.get_height(),
+ pixbuf.get_rowstride()
+ );
+ this.cover = image.get_texture();
+ }
+ if (this._applet.keepAlbumAspectRatio) {
+ //TODO: Replace Texture by Image.
+ this.cover = new Clutter.Texture({
+ width: Math.trunc(300*global.ui_scale),
+ keep_aspect_ratio: true,
+ //filter_quality: 2,
+ filter_quality: Clutter.Texture.QUALITY_HIGH,
+ filename: cover_path
+ });
+ }
+ else {
+ //TODO: Replace Texture by Image.
+ this.cover = new Clutter.Texture({
+ width: Math.trunc(300*global.ui_scale),
+ height: Math.trunc(300*global.ui_scale),
+ keep_aspect_ratio: false,
+ filter_quality: Clutter.Texture.QUALITY_HIGH,
+ filename: cover_path
+ });
+ }
+ //~ this.display_cover_button.show();
+ } catch(e) {}
+ }
+ }
+
+ _on_cover_loaded(cache, handle, actor) {
+ if (handle !== this._cover_load_handle) {
+ // Maybe a cover image load stalled? Make sure our requests match the callback.
+ return;
+ }
+
+ try {
+ this.coverBox.remove_actor(this.cover);
+ } catch(e) {}
+
+ // Make sure any oddly-shaped album art doesn't affect the height of the applet popup
+ // (and move the player controls as a result).
+ //~ log("actor size (wxh): "+actor.width+"x"+actor.height, true);
+ actor.set_margin_bottom(Math.max(0, Math.trunc(300*global.ui_scale - actor.height)));
+ actor.set_margin_left(Math.max(0, Math.trunc(300*global.ui_scale - actor.width)));
+
+ this.cover = actor;
+ this.coverBox.add_actor(this.cover);
+ //~ this.coverBox.set_reactive = true;
+ //~ this.coverBox.connect("button-press-event", (event) => Util.spawnCommandLineAsync("xdg-open "+this._cover_path));
+
+ try { this.coverBox.set_child_below_sibling(this.cover, this.trackInfo);} catch(e) {}
+ this._applet.setAppletTextIcon(this, this._cover_path);
+ }
+
+ onSettingsChanged() {
+ this._loopButton.actor.visible = this._applet.extendedPlayerControl && this._mediaServerPlayer.LoopStatus;
+ this._shuffleButton.actor.visible = this._applet.extendedPlayerControl && this._mediaServerPlayer.Shuffle;
+ }
+
+ destroy() {
+ //~ if (this._seeker)
+ //~ this._seeker.destroy();
+ if (this._prop && this._propChangedId)
+ this._prop.disconnectSignal(this._propChangedId);
+
+ if (this._seeker)
+ this._seeker.destroy();
+
+ try {
+ PopupMenu.PopupMenuSection.prototype.destroy.call(this);
+ } catch(e) {logError("Error destroying Player!!!: "+e)}
+ }
+}
+
+class MediaPlayerLauncher extends PopupMenu.PopupBaseMenuItem {
+ constructor(app, menu) {
+ super({});
+
+ this._app = app;
+ this._menu = menu;
+ this.label = new St.Label({ text: app.get_name() });
+ this.addActor(this.label);
+ this._icon = app.create_icon_texture(ICON_SIZE);
+ this._icon_bin = new St.Bin({ x_align: St.Align.END, child: this._icon });
+ try {
+ this.addActor(this._icon_bin, { expand: true, span: -1, align: St.Align.END });
+ } catch(e) {logError("Unable to add actor this._icon_bin to this!: "+e)}
+
+ this.connect("activate", (event) => this._onActivate(event));
+ }
+
+ _onActivate(event) {
+ let _time = event.time;
+ this._app.activate_full(-1, _time);
+ }
+}
+
+class Sound150Applet extends Applet.TextIconApplet {
+ constructor(metadata, orientation, panel_height, instanceId) {
+ super(orientation, panel_height, instanceId);
+
+ Util.spawnCommandLineAsync("bash -c 'cd %s && chmod 755 *.sh'".format(PATH2SCRIPTS));
+ Util.spawnCommandLineAsync("bash -C '"+ PATH2SCRIPTS +"/rm_tmp_files.sh'");
+
+ this.orientation = orientation;
+ this.isHorizontal = !(this.orientation == St.Side.LEFT || this.orientation == St.Side.RIGHT);
+ this.setAllowedLayout(Applet.AllowedLayout.BOTH);
+
+ this.metadata = metadata;
+
+ this.oldPlayerIcon0 = null;
+
+ this.title_text = "";
+
+ this.settings = new Settings.AppletSettings(this, metadata.uuid, instanceId);
+ this.settings.bind("showOSDonStartup", "showOSDonStartup");
+ this.showOSD = this.showOSDonStartup;
+ this.settings.bind("seekerTooltipDelay", "seekerTooltipDelay");
+ this.settings.bind("soundATcinnamonDOTorg_is_loaded", "soundATcinnamonDOTorg_is_loaded");
+ this.settings.bind("showtrack", "showtrack", this.on_settings_changed);
+ this.settings.bind("middleClickAction", "middleClickAction");
+ this.settings.bind("middleShiftClickAction", "middleShiftClickAction");
+ this.settings.bind("horizontalScroll", "horizontalScroll");
+ this.settings.bind("showalbum", "showalbum", this.on_settings_changed);
+ this.settings.bind("truncatetext", "truncatetext", this.on_settings_changed);
+ this.settings.bind("keepAlbumAspectRatio", "keepAlbumAspectRatio", this.on_settings_changed);
+ this.settings.bind("hideSystray", "hideSystray", function () {
+ if (this.hideSystray) this.registerSystrayIcons();
+ else this.unregisterSystrayIcons();
+ });
+
+ this.settings.bind("playerControl", "playerControl", this.on_settings_changed);
+ this.settings.bind("extendedPlayerControl", "extendedPlayerControl", function() {
+ for (let i in this._players)
+ this._players[i].onSettingsChanged();
+ });
+ this.settings.bind("avoidTwice", "avoidTwice", this._updatePlayerMenuItems);
+
+
+ this.settings.bind("_knownPlayers", "_knownPlayers");
+ if (this.hideSystray) this.registerSystrayIcons();
+
+ this.settings.bind("keyOpen", "keyOpen", this._setKeybinding);
+ this.settings.bind("keySwitchPlayer", "keySwitchPlayer", this._setKeybinding);
+
+ this.settings.bind("stepVolume", "stepVolume", () => {
+ VOLUME_ADJUSTMENT_STEP = this.settings.getValue("stepVolume") / 100;
+ //~ log("VOLUME_ADJUSTMENT_STEP = " + VOLUME_ADJUSTMENT_STEP);
+ });
+ VOLUME_ADJUSTMENT_STEP = this.settings.getValue("stepVolume") / 100;
+ //~ log("VOLUME_ADJUSTMENT_STEP = " + VOLUME_ADJUSTMENT_STEP);
+
+ this.settings.bind("magneticOn", "magneticOn", () => this._on_sound_settings_change());
+ this.settings.bind("magnetic25On", "magnetic25On", () => this._on_sound_settings_change());
+
+ this.settings.bind("adaptColor", "adaptColor", () => this._on_sound_settings_change());
+ this.settings.bind("color101_115", "color101_115", () => this._on_sound_settings_change());
+ this.settings.bind("color116_130", "color116_130", () => this._on_sound_settings_change());
+ this.settings.bind("color131_150", "color131_150", () => this._on_sound_settings_change());
+
+
+ this.settings.bind("tooltipShowVolume", "tooltipShowVolume", this.on_settings_changed);
+ this.settings.bind("tooltipShowPlayer", "tooltipShowPlayer", this.on_settings_changed);
+ this.settings.bind("tooltipShowArtistTitle", "tooltipShowArtistTitle", this.on_settings_changed);
+
+ this.settings.bind("alwaysCanChangeMic", "alwaysCanChangeMic", this.on_settings_changed);
+
+ this._sounds_settings = new Gio.Settings({ schema_id: CINNAMON_DESKTOP_SOUNDS });
+ this.settings.setValue("volumeSoundFile", this._sounds_settings.get_string(VOLUME_SOUND_FILE_KEY));
+ this.settings.bind("volumeSoundFile", "volumeSoundFile", this.on_volumeSoundFile_changed);
+ this.settings.setValue("volumeSoundEnabled", this._sounds_settings.get_boolean(VOLUME_SOUND_ENABLED_KEY));
+ this.settings.bind("volumeSoundEnabled", "volumeSoundEnabled", this.on_volumeSoundEnabled_changed);
+
+ this.settings.setValue("showMediaKeysOSD", global.settings.get_string(SHOW_MEDIA_KEYS_OSD_KEY));
+ this.settings.bind("showMediaKeysOSD", "showMediaKeysOSD", this.on_showMediaKeysOSD_changed);
+ this.showOSD = this.showOSDonStartup && (this.showMediaKeysOSD != "disabled");
+
+ this.settings.bind("volume", "volume");
+ this.settings.bind("mic-level", "mic_level");
+ this.settings.bind("showVolumeLevelNearIcon", "showVolumeLevelNearIcon", this.volume_near_icon);
+ this.settings.bind("showMicMutedOnIcon", "showMicMutedOnIcon", () => this._on_sound_settings_change());
+ this.settings.bind("showMicUnmutedOnIcon", "showMicUnmutedOnIcon", () => this._on_sound_settings_change());
+ this.settings.bind("redefine-volume-keybindings", "redefine_volume_keybindings", this._setKeybinding);
+ this.settings.bind("audio-stop", "audio_stop", this._setKeybinding);
+ this.settings.bind("pause-on-off", "pause_on_off", this._setKeybinding);
+ this.settings.bind("volume-mute", "volume_mute", this._setKeybinding);
+ this.settings.bind("volume-up", "volume_up", this._setKeybinding);
+ this.settings.bind("volume-down", "volume_down", this._setKeybinding);
+ this.settings.bind("audio-next", "audio_next", this._setKeybinding);
+ this.settings.bind("audio-prev", "audio_prev", this._setKeybinding);
+
+ // Whether sound@cinnamon.org is loaded:
+ let enabledApplets = global.settings.get_strv(ENABLED_APPLETS_KEY);
+ var _soundATcinnamonDOTorg_is_loaded = false;
+ for (let appData of enabledApplets) {
+ if (appData.toString().split(":")[3] === "sound@cinnamon.org") {
+ _soundATcinnamonDOTorg_is_loaded = true;
+ break;
+ }
+ }
+ this.settings.setValue("soundATcinnamonDOTorg_is_loaded", _soundATcinnamonDOTorg_is_loaded);
+
+ Main.themeManager.connect("theme-set", Lang.bind(this, this._theme_set));
+
+ this.menuManager = new PopupMenu.PopupMenuManager(this);
+ this.menu = new Applet.AppletPopupMenu(this, orientation);
+ this.menuManager.addMenu(this.menu);
+ this._setKeybinding();
+
+ this.set_applet_icon_symbolic_name("audio-x-generic");
+
+ this._players = {};
+ this._playerItems = [];
+ this._activePlayer = null;
+
+ Interfaces.getDBusAsync((proxy, error) => {
+ if (error) {
+ // ?? what else should we do if we fail completely here?
+ throw error;
+ }
+
+ this._dbus = proxy;
+
+ // player DBus name pattern
+ let name_regex = /^org\.mpris\.MediaPlayer2\./;
+ // load players
+ this._dbus.ListNamesRemote((names) => {
+ for (let n in names[0]) {
+ let name = names[0][n];
+ if (name_regex.test(name))
+ this._dbus.GetNameOwnerRemote(name, (owner) => this._addPlayer(name, owner[0]));
+ }
+ });
+
+ // watch players
+ this._ownerChangedId = this._dbus.connectSignal("NameOwnerChanged",
+ (proxy, sender, [name, old_owner, new_owner]) => {
+ if (name_regex.test(name)) {
+ if (new_owner && !old_owner)
+ this._addPlayer(name, new_owner);
+ else if (old_owner && !new_owner)
+ this._removePlayer(name, old_owner);
+ else
+ this._changePlayerOwner(name, old_owner, new_owner);
+ }
+ }
+ );
+ });
+
+ this._control = new Cvc.MixerControl({ name: "Sound150 Volume Control" });
+ this._control.connect("state-changed", (...args) => this._onControlStateChanged(...args));
+
+ this._control.connect("output-added", (...args) => this._onDeviceAdded(...args, "output"));
+ this._control.connect("output-removed", (...args) => this._onDeviceRemoved(...args, "output"));
+ this._control.connect("active-output-update", (...args) => this._onDeviceUpdate(...args, "output"));
+
+ this._control.connect("input-added", (...args) => this._onDeviceAdded(...args, "input"));
+ this._control.connect("input-removed", (...args) => this._onDeviceRemoved(...args, "input"));
+ this._control.connect("active-input-update", (...args) => this._onDeviceUpdate(...args, "input"));
+
+ this._control.connect("stream-added", (...args) => this._onStreamAdded(...args));
+ this._control.connect("stream-removed", (...args) => this._onStreamRemoved(...args));
+
+ //~ this._sound_settings = new Gio.Settings({ schema_id: CINNAMON_DESKTOP_SOUNDS });
+ this._volumeNorm = this._control.get_vol_max_norm();
+ this._volumeMax = this._volumeNorm;
+
+ this._streams = [];
+ this._devices = [];
+ this._recordingAppsNum = 0;
+
+ this._output = null;
+ this._outputMutedId = 0;
+ this._outputIcon = "audio-volume-muted-symbolic";
+
+ this._input = null;
+ this._inputMutedId = 0;
+
+ this._icon_name = '';
+ this._icon_path = null;
+ this._iconTimeoutId = null;
+
+ this.actor.connect("scroll-event", (...args) => this._onScrollEvent(...args));
+ this.actor.connect("key-press-event", (...args) => this._onKeyPressEvent(...args));
+
+ this.mute_out_switch = new PopupMenu.PopupSwitchIconMenuItem(_("Mute output"), false, "audio-volume-muted-symbolic", St.IconType.SYMBOLIC);
+ this.mute_in_switch = new PopupMenu.PopupSwitchIconMenuItem(_("Mute input"), false, "microphone-sensitivity-muted-symbolic", St.IconType.SYMBOLIC);
+ this._applet_context_menu.addMenuItem(this.mute_out_switch);
+ this._applet_context_menu.addMenuItem(this.mute_in_switch);
+ if (!this.alwaysCanChangeMic)
+ this.mute_in_switch.actor.hide();
+ else
+ this.mute_in_switch.actor.show();
+
+ this._applet_context_menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+ this._outputApplicationsMenu = new PopupMenu.PopupSubMenuMenuItem(_("Applications"));
+ this._selectOutputDeviceItem = new PopupMenu.PopupSubMenuMenuItem(_("Output device"));
+ this._applet_context_menu.addMenuItem(this._outputApplicationsMenu);
+ this._applet_context_menu.addMenuItem(this._selectOutputDeviceItem);
+ this._outputApplicationsMenu.actor.hide();
+ this._selectOutputDeviceItem.actor.hide();
+
+ this._inputSection = new PopupMenu.PopupMenuSection();
+ this._inputVolumeSection = new VolumeSlider(this, null, _("Microphone"), null);
+ this._inputVolumeSection.connect("values-changed", (...args) => this._inputValuesChanged(...args));
+ this._selectInputDeviceItem = new PopupMenu.PopupSubMenuMenuItem(_("Input device"));
+ //this._inputSection.addMenuItem(this._inputVolumeSection);
+ this._inputSection.addMenuItem(this._selectInputDeviceItem);
+ this._applet_context_menu.addMenuItem(this._inputSection);
+
+ this._selectInputDeviceItem.actor.show(); //.hide();
+ this._inputSection.actor.show(); //.hide();
+
+ this._applet_context_menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+ let easy_effects = this.get_effects("Easy Effects");
+ //~ log("easy_effects: "+easy_effects, true);
+ if (easy_effects) {
+ this.context_menu_item_easyEffects = new PopupMenu.PopupIconMenuItem(_("Easy Effects"), "easyeffects", St.IconType.SYMBOLIC);
+ this.context_menu_item_easyEffects.connect("activate", async () => { Util.spawnCommandLine("%s".format(easy_effects)) });
+ this._applet_context_menu.addMenuItem(this.context_menu_item_easyEffects);
+ }
+
+ let pulse_effects = this.get_effects("PulseEffects");
+ if (pulse_effects) {
+ this.context_menu_item_pulseEffects = new PopupMenu.PopupIconMenuItem(_("Pulse Effects"), "pulseeffects", St.IconType.SYMBOLIC);
+ this.context_menu_item_pulseEffects.connect("activate", async () => { Util.spawnCommandLine("%s".format(pulse_effects)) });
+ this._applet_context_menu.addMenuItem(this.context_menu_item_pulseEffects);
+ }
+
+ this.mute_out_switch.connect("toggled", () => this._toggle_out_mute());
+ this.mute_in_switch.connect("toggled", () => this._toggle_in_mute());
+
+ this._control.open();
+
+ this._volumeControlShown = false;
+
+ this._showFixedElements();
+ this.set_show_label_in_vertical_panels(false);
+ this.set_applet_label(this._applet_label.get_text());
+
+ let appsys = Cinnamon.AppSystem.get_default();
+ appsys.connect("installed-changed", () => this._updateLaunchPlayer());
+
+ this._sound_settings.connect("changed::" + OVERAMPLIFICATION_KEY, () => this._on_sound_settings_change());
+ this._on_sound_settings_change();
+
+ this._loopArtId = null;
+ this.loopArt();
+ }
+
+ on_volumeSoundFile_changed() {
+ this._sounds_settings.set_string(VOLUME_SOUND_FILE_KEY, this.volumeSoundFile);
+ }
+
+ on_volumeSoundEnabled_changed() {
+ this._sounds_settings.set_boolean(VOLUME_SOUND_ENABLED_KEY, this.volumeSoundEnabled);
+ }
+
+ on_showMediaKeysOSD_changed() {
+ global.settings.set_string(SHOW_MEDIA_KEYS_OSD_KEY, this.showMediaKeysOSD);
+ }
+
+ _on_remove_soundATcinnamonDOTorg_from_panels() {
+ const TO_REMOVE = "sound@cinnamon.org";
+ let dialog = new ModalDialog.ConfirmDialog(
+ _("Are you sure you want to remove '%s'?").format(TO_REMOVE),
+ () => {
+ Extension.unloadExtension(TO_REMOVE, Extension.Type.APPLET, false, false);
+
+ let oldList = global.settings.get_strv(ENABLED_APPLETS_KEY);
+ let newList = [];
+
+ for (let i = 0; i < oldList.length; i++) {
+ let info = oldList[i].split(":");
+ if (info[3] != TO_REMOVE) {
+ newList.push(oldList[i]);
+ }
+ }
+ global.settings.set_strv(ENABLED_APPLETS_KEY, newList);
+ this.settings.setValue("soundATcinnamonDOTorg_is_loaded", false);
+ this._on_reload_this_applet_pressed();
+ }
+ );
+ dialog.open();
+ }
+
+ get_effects(name) {
+ var commandline = null;
+ let appsys = Cinnamon.AppSystem.get_default();
+ const dirs = [];
+ const iter = appsys.get_tree().get_root_directory().iter();
+ const CMenu = imports.gi.CMenu;
+
+ let nextType;
+ while ((nextType = iter.next()) !== CMenu.TreeItemType.INVALID) {
+ if (nextType === CMenu.TreeItemType.DIRECTORY) {
+ dirs.push(iter.get_directory());
+ }
+
+ dirs.forEach(dir => {
+ if (!dir.get_is_nodisplay()) {
+ const dirId = dir.get_menu_id();
+ //~ log("dirId: "+dirId, true);
+ if (dirId === "Multimedia") {
+ const dirIter = dir.iter();
+ let nextTypeDir;
+ while ((nextTypeDir = dirIter.next()) !== CMenu.TreeItemType.INVALID) {
+ const entry = dirIter.get_entry();
+ if (entry == null) continue;
+ const appInfo = entry.get_app_info();
+ if (appInfo && !appInfo.get_nodisplay()) {
+ const id = entry.get_desktop_file_id();
+ const app = appsys.lookup_app(id);
+ //~ log("APP NAME: "+app.get_name(), true);
+ if (app.get_name() == name) {
+ commandline = appInfo.get_commandline();
+ break;
+ }
+ }
+ }
+ }
+ }
+ });
+ }
+ return commandline;
+ }
+
+ _setKeybinding() {
+ Main.keybindingManager.addHotKey("sound-open-" + this.instance_id, this.keyOpen, Lang.bind(this, this._openMenu));
+ Main.keybindingManager.addHotKey("switch-player-" + this.instance_id, this.keySwitchPlayer, Lang.bind(this, this._switchToNextPlayer));
+
+ Main.keybindingManager.addHotKey("raise-volume-" + this.instance_id, "AudioRaiseVolume", () => this._volumeChange(Clutter.ScrollDirection.UP));
+ Main.keybindingManager.addHotKey("lower-volume-" + this.instance_id, "AudioLowerVolume", () => this._volumeChange(Clutter.ScrollDirection.DOWN));
+ Main.keybindingManager.addHotKey("volume-mute-" + this.instance_id, "AudioMute", () => this._toggle_out_mute());
+ Main.keybindingManager.addHotKey("pause-" + this.instance_id, "AudioPlay", () => this._players[this._activePlayer]._mediaServerPlayer.PlayPauseRemote());
+
+ Main.keybindingManager.addHotKey("audio-next-" + this.instance_id, "AudioNext", () => {
+ if (this._players[this._activePlayer]._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Next", "");
+ } else {
+ this._players[this._activePlayer]._mediaServerPlayer.NextRemote()
+ }
+ });
+ Main.keybindingManager.addHotKey("audio-prev-" + this.instance_id, "AudioPrev", () => {
+ if (this._players[this._activePlayer]._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Previous", "");
+ } else {
+ this._players[this._activePlayer]._mediaServerPlayer.PreviousRemote()
+ }
+ });
+ Main.keybindingManager.addHotKey("audio-stop-" + this.instance_id, "AudioStop", () => {
+ if (this._players[this._activePlayer]._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Stop", "");
+ } else {
+ this._players[this._activePlayer]._mediaServerPlayer.StopRemote()
+ }
+ });
+
+ if (!this.redefine_volume_keybindings) return;
+
+ try {
+ Main.keybindingManager.removeHotKey("media-keys-4");
+ Main.keybindingManager.removeHotKey("media-keys-2");
+ } catch(e) {logError("Unable to removeHotKey media-keys: "+e)}
+
+ Main.keybindingManager.removeHotKey("raise-volume");
+ Main.keybindingManager.removeHotKey("lower-volume");
+ Main.keybindingManager.removeHotKey("volume-mute");
+ Main.keybindingManager.removeHotKey("volume-up");
+ Main.keybindingManager.removeHotKey("volume-down");
+ Main.keybindingManager.removeHotKey("pause");
+ Main.keybindingManager.removeHotKey("audio-stop");
+
+ Main.keybindingManager.removeHotKey("audio-next");
+ Main.keybindingManager.removeHotKey("audio-prev");
+
+ if (this.audio_stop.length > 2)
+ Main.keybindingManager.addHotKey("audio-stop", this.audio_stop,
+ () => {
+ //~ logDebug("_name: "+this._players[this._activePlayer]._name);
+ if (this._players[this._activePlayer]._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Stop", "");
+ } else {
+ this._players[this._activePlayer]._mediaServerPlayer.StopRemote()
+ }
+ });
+
+ if (this.pause_on_off.length > 2)
+ Main.keybindingManager.addHotKey("pause", this.pause_on_off,
+ () => this._players[this._activePlayer]._mediaServerPlayer.PlayPauseRemote());
+ if (this.volume_mute.length > 2)
+ Main.keybindingManager.addHotKey("volume-mute", this.volume_mute, () => this._toggle_out_mute());//(...args) => this._mutedChanged(...args, "_output"));
+ if (this.volume_up.length > 2)
+ Main.keybindingManager.addHotKey("volume-up", this.volume_up, () => this._volumeChange(Clutter.ScrollDirection.UP));
+ if (this.volume_down.length > 2)
+ Main.keybindingManager.addHotKey("volume-down", this.volume_down, () => this._volumeChange(Clutter.ScrollDirection.DOWN));
+ if (this.audio_next.length > 2)
+ Main.keybindingManager.addHotKey("audio-next", this.audio_next, () => {
+ if (this._players[this._activePlayer]._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Next", "");
+ } else {
+ this._players[this._activePlayer]._mediaServerPlayer.NextRemote()
+ }
+ });
+
+ if (this.audio_prev.length > 2)
+ Main.keybindingManager.addHotKey("audio-prev", this.audio_prev, () => {
+ if (this._players[this._activePlayer]._name.toLowerCase() === "mpv"
+ && GLib.file_test(R30MPVSOCKET, GLib.FileTest.EXISTS)) {
+ GLib.file_set_contents(RUNTIME_DIR + "/R30Previous", "");
+ } else {
+ this._players[this._activePlayer]._mediaServerPlayer.PreviousRemote()
+ }
+ });
+ } // End of _setKeybinding
+
+ _on_sound_settings_change() {
+ if (this._sound_settings.get_boolean(OVERAMPLIFICATION_KEY)) {
+ this._volumeMax = 1.5 * this._volumeNorm;
+ this._outputVolumeSection.set_mark(1/1.5);
+ }
+ else {
+ this._volumeMax = this._volumeNorm;
+ this._outputVolumeSection.set_mark(0);
+ }
+ this._outputVolumeSection._update();
+ }
+
+ on_orientation_changed() {
+ this.orientation = orientation;
+ this.isHorizontal = !(this.orientation == St.Side.LEFT || this.orientation == St.Side.RIGHT);
+ }
+
+ on_settings_changed() {
+ if (this.playerControl && this._activePlayer)
+ this.setAppletTextIcon(this._players[this._activePlayer], true);
+ else
+ this.setAppletTextIcon();
+
+ if (this.alwaysCanChangeMic)
+ this.mute_in_switch.actor.show();
+ else if (this._recordingAppsNum === 0)
+ this.mute_in_switch.actor.hide();
+
+ this._changeActivePlayer(this._activePlayer);
+ }
+
+ on_applet_added_to_panel() {
+ this.showOSD = this.showOSDonStartup && (this.showMediaKeysOSD != "disabled");
+ this.volume_near_icon()
+ }
+
+ on_applet_reloaded() {
+ this.showOSD = this.showOSDonStartup && (this.showMediaKeysOSD != "disabled");
+ }
+
+ on_applet_removed_from_panel() {
+ Main.keybindingManager.removeHotKey("sound-open-" + this.instance_id);
+ Main.keybindingManager.removeHotKey("switch-player-" + this.instance_id);
+ try {
+ Main.keybindingManager.removeHotKey("raise-volume-" + this.instance_id);
+ Main.keybindingManager.removeHotKey("lower-volume-" + this.instance_id);
+ Main.keybindingManager.removeHotKey("volume-mute-" + this.instance_id);
+ Main.keybindingManager.removeHotKey("pause-" + this.instance_id);
+ Main.keybindingManager.removeHotKey("audio-next-" + this.instance_id);
+ Main.keybindingManager.removeHotKey("audio-prev-" + this.instance_id);
+ } catch(e) {}
+
+ if (this.redefine_volume_keybindings) {
+ try {
+ Main.keybindingManager.removeHotKey("volume-mute");
+ Main.keybindingManager.removeHotKey("volume-up");
+ Main.keybindingManager.removeHotKey("volume-down");
+ Main.keybindingManager.removeHotKey("pause");
+ Main.keybindingManager.removeHotKey("audio-next");
+ Main.keybindingManager.removeHotKey("audio-prev");
+ } catch(e) {}
+ }
+
+ if (this.hideSystray)
+ this.unregisterSystrayIcons();
+ if (this._iconTimeoutId) {
+ try {Mainloop.source_remove(this._iconTimeoutId);} catch(e) {}
+ this._iconTimeoutId = null;
+ }
+ if (this._loopArtId) {
+ try {Mainloop.source_remove(this._loopArtId);} catch(e) {}
+ this._loopArtId = null;
+ }
+ if (this._seeker && this._seeker._timeoutId) {
+ try {Mainloop.source_remove(this._seeker._timeoutId);} catch(e) {}
+ this._seeker._timeoutId = 0;
+ }
+
+ if (this._ownerChangedId) {
+ this._dbus.disconnectSignal(this._ownerChangedId);
+ this._ownerChangedId = 0;
+ }
+
+ for (let i in this._players)
+ if (this._players[i])
+ this._players[i].destroy();
+
+ if (this._control)
+ this._control.close();
+ }
+
+ on_applet_clicked(event) {
+ this._openMenu();
+ if (!this.menu.isOpen) return;
+ let kplo = this.settings.getValue("keepPlayerListOpen");
+ if (!this._chooseActivePlayerItemActorIsHidden && this.settings.getValue("keepChoosePlayerOpen"))
+ this._chooseActivePlayerItem.menu.open();
+ if (!this._launchPlayerItemActorIsHidden && kplo)
+ this._launchPlayerItem.menu.open();
+ }
+
+ _openMenu() {
+ this.menu.toggle();
+ }
+
+ _toggle_out_mute() {
+ if (!this._output)
+ return;
+
+ if (this._output.is_muted) {
+ this._output.change_is_muted(false);
+ this.mute_out_switch.setToggleState(false);
+ } else {
+ this._output.change_is_muted(true);
+ this.mute_out_switch.setToggleState(true);
+ this._outputIcon = "audio-volume-muted-symbolic";
+ this.set_applet_icon_symbolic_name(this._outputIcon);
+ }
+ }
+
+ _toggle_in_mute() {
+ if (!this._input) {
+ this.showOSD = (this.showMediaKeysOSD != "disabled");
+ this._volumeChange(null);
+ return;
+ }
+
+ let newStatus = !this._input.is_muted;
+ this._input.change_is_muted(newStatus);
+ this.mute_in_switch.setToggleState(newStatus);
+ this.showOSD = (this.showMediaKeysOSD != "disabled");
+ this._volumeChange(null);
+ }
+
+ _onScrollEvent(actor, event) {
+ //~ logDebug("event: "+event.originalEvent.ctrlKey);
+ let _event = event;
+ this.showOSD = (this.showMediaKeysOSD != "disabled");
+ let modifiers = Cinnamon.get_event_state(event);
+ let shiftPressed = (modifiers & Clutter.ModifierType.SHIFT_MASK);
+ let ctrlPressed = (modifiers & Clutter.ModifierType.CONTROL_MASK);
+ if (ctrlPressed || shiftPressed) {
+ this._inputVolumeSection._onScrollEvent(this._inputVolumeSection.actor, _event);
+ return
+ }
+
+ const direction = event.get_scroll_direction();
+
+ if (direction == Clutter.ScrollDirection.SMOOTH) {
+ //~ let [dx, dy] = event.get_scroll_delta();
+ //~ logDebug("Scroll delta - dx: "+dx+" dy: "+dy);
+ return Clutter.EVENT_PROPAGATE;
+ }
+
+ this._volumeChange(direction);
+ this.volume_near_icon()
+ }
+
+ _volumeChange(direction) {
+ if (this._sounds_settings) {
+ this.volumeSoundEnabled = this._sounds_settings.get_boolean(VOLUME_SOUND_ENABLED_KEY);
+ this.volumeSoundFile = this._sounds_settings.get_string(VOLUME_SOUND_FILE_KEY);
+ }
+ let currentVolume = this._output.volume;
+ let volumeChange = (direction === null) ? true : false;
+ let player = this._players[this._activePlayer];
+
+ if (direction !== null) {
+ if (direction == Clutter.ScrollDirection.DOWN) {
+ let prev_muted = this._output.is_muted;
+ this._output.volume = Math.max(0, currentVolume - this._volumeNorm * VOLUME_ADJUSTMENT_STEP);
+ if (this._output.volume < 1) {
+ this._output.volume = 0;
+ if (!prev_muted)
+ this._output.change_is_muted(true);
+ this._outputIcon = "audio-volume-muted-symbolic";
+ this.set_applet_icon_symbolic_name(this._outputIcon);
+ } else {
+ // 100% is magnetic:
+ if (this.magneticOn === true && this._output.volume != this._volumeNorm && this._output.volume > this._volumeNorm * (1 - VOLUME_ADJUSTMENT_STEP / 2) && this._output.volume < this._volumeNorm * (1 + VOLUME_ADJUSTMENT_STEP / 2))
+ this._output.volume = this._volumeNorm;
+
+ if (this.magneticOn === true && this.magnetic25On === true) {
+ for (let i = 0.25; i < 1.5; i+=0.25) {
+ if (i==1) continue;
+ if (this._output.volume != i*this._volumeNorm && this._output.volume > this._volumeNorm * (i - VOLUME_ADJUSTMENT_STEP / 2) && this._output.volume < this._volumeNorm * (i + VOLUME_ADJUSTMENT_STEP / 2))
+ this._output.volume = i*this._volumeNorm;
+ }
+ }
+ }
+
+ volumeChange = true;
+ }
+ else if (direction == Clutter.ScrollDirection.UP) {
+ this._output.volume = Math.min(this._volumeMax, currentVolume + this._volumeNorm * VOLUME_ADJUSTMENT_STEP);
+ // 100% is magnetic:
+ if (this.magneticOn === true && this._output.volume != this._volumeNorm && this._output.volume > this._volumeNorm * (1 - VOLUME_ADJUSTMENT_STEP / 2) && this._output.volume < this._volumeNorm * (1 + VOLUME_ADJUSTMENT_STEP / 2))
+ this._output.volume = this._volumeNorm;
+
+ if (this.magneticOn === true && this.magnetic25On === true) {
+ for (let i = 0.25; i < 1.5; i+=0.25) {
+ if (i==1) continue;
+ if (this._output.volume != i*this._volumeNorm && this._output.volume > this._volumeNorm * (i - VOLUME_ADJUSTMENT_STEP / 2) && this._output.volume < this._volumeNorm * (i + VOLUME_ADJUSTMENT_STEP / 2))
+ this._output.volume = i*this._volumeNorm;
+ }
+ }
+
+ this._output.change_is_muted(false);
+ volumeChange = true;
+ }
+ else if (this.horizontalScroll && player !== null && player._playerStatus !== "Stopped") {
+ if (direction == Clutter.ScrollDirection.LEFT) {
+ this._players[this._activePlayer]._mediaServerPlayer.PreviousRemote();
+ }
+ else if (direction == Clutter.ScrollDirection.RIGHT) {
+ this._players[this._activePlayer]._mediaServerPlayer.NextRemote();
+ }
+ }
+ }
+
+ if (volumeChange) {
+ this._output.push_volume();
+ this._notifyVolumeChange(this._output);
+ this.setAppletTooltip();
+ this._applet_tooltip.show();
+ let volume = this.volume.slice(0, -1);
+ let icon_name = "audio-volume";
+ if (volume > 100) icon_name += "-overamplified";
+ else if (volume <1) {
+ icon_name += "-muted";
+ volume = 0;
+ this.volume = "0%";
+ }
+ else if (volume < 33) icon_name += "-low";
+ else if (volume < 67) icon_name += "-medium";
+ else icon_name += "-high";
+ if (this.showMicMutedOnIcon &&
+ (!this.mute_in_switch || this.mute_in_switch.state)
+ )
+ icon_name += "-with-mic-disabled";
+ else if (this.showMicUnmutedOnIcon &&
+ (this.mute_in_switch && !this.mute_in_switch.state)
+ )
+ icon_name += "-with-mic-enabled";
+ icon_name += "-symbolic";
+ let icon = Gio.Icon.new_for_string(icon_name);
+ this.set_applet_icon_symbolic_name(icon_name);
+ if (this.showOSD) {
+ //~ Main.osdWindowManager.hideAll();
+ Main.osdWindowManager.show(-1, icon, volume, null);
+ //Main.osdWindowManager.show(0, icon, volume, true);
+ }
+ var intervalId = null;
+ intervalId = Util.setInterval(() => {
+ this._applet_tooltip.hide();
+ Util.clearInterval(intervalId);
+ return false
+ }, 5000);
+ } else {
+ this._applet_tooltip.hide();
+ }
+
+ this.showOSD = (this.showMediaKeysOSD != "disabled");
+
+ this.volume_near_icon()
+ }
+
+ _onButtonPressEvent(actor, event) {
+ let buttonId = event.get_button();
+ let modifiers = Cinnamon.get_event_state(event);
+ let shiftPressed = (modifiers & Clutter.ModifierType.SHIFT_MASK);
+ let ctrlPressed = (modifiers & Clutter.ModifierType.CONTROL_MASK);
+
+ // mute or play / pause players on middle click
+ if (buttonId === 2) {
+ if (shiftPressed || ctrlPressed) {
+ if (this.middleShiftClickAction === "mute") {
+ if (this._input && this._output && this._output.is_muted === this._input.is_muted)
+ this._toggle_in_mute();
+ this._toggle_out_mute();
+ } else if (this.middleShiftClickAction === "out_mute")
+ this._toggle_out_mute();
+ else if (this.middleShiftClickAction === "in_mute")
+ this._toggle_in_mute();
+ else if (this.middleShiftClickAction === "player")
+ this._players[this._activePlayer]._mediaServerPlayer.PlayPauseRemote();
+ } else {
+ if (this.middleClickAction === "mute") {
+ if (this._input && this._output && this._output.is_muted === this._input.is_muted)
+ this._toggle_in_mute();
+ this._toggle_out_mute();
+ } else if (this.middleClickAction === "out_mute")
+ this._toggle_out_mute();
+ else if (this.middleClickAction === "in_mute")
+ this._toggle_in_mute();
+ else if (this.middleClickAction === "player")
+ this._players[this._activePlayer]._mediaServerPlayer.PlayPauseRemote();
+ }
+ } else if (buttonId === 8) { // previous and next track on mouse buttons 4 and 5 (8 and 9 by X11 numbering)
+ this._players[this._activePlayer]._mediaServerPlayer.PreviousRemote();
+ } else if (buttonId === 9) {
+ this._players[this._activePlayer]._mediaServerPlayer.NextRemote();
+ } else {
+ return Applet.Applet.prototype._onButtonPressEvent.call(this, actor, event);
+ }
+ return Clutter.EVENT_STOP;
+ }
+
+ _onKeyPressEvent(actor, event) {
+ let key = event.get_key_symbol();
+ if (key == Clutter.KEY_Right ||
+ key == Clutter.KEY_Left ||
+ key == Clutter.KEY_AudioRaiseVolume ||
+ key == Clutter.KEY_AudioLowerVolume) {
+ return this._outputVolumeSection._onKeyPressEvent(this._outputVolumeSection.actor, event);
+ }
+ return false;
+ }
+
+ setIcon(icon, source) {
+ //~ log("setIcon("+icon+", "+source+")", true);
+ if (this._iconTimeoutId) {
+ try {Mainloop.source_remove(this._iconTimeoutId)} catch(e) {}
+ this._iconTimeoutId = null;
+ }
+
+ // save the icon
+ if (source) {
+ if (source === "output")
+ this._outputIcon = icon;
+ else
+ this._playerIcon = [icon, source === "player-path"];
+ }
+
+ if (this.playerControl && this._activePlayer && this._playerIcon[0]) {
+ if (source === "output") {
+ // if we have an active player, but are changing the volume, show the output icon and after three seconds change back to the player icon
+ this.set_applet_icon_symbolic_name(this._outputIcon);
+ if (this._iconTimeoutId) {
+ try {Mainloop.source_remove(this._iconTimeoutId);} catch(e) {}
+ this._iconTimeoutId = null;
+ }
+ this._iconTimeoutId = Mainloop.timeout_add_seconds(OUTPUT_ICON_SHOW_TIME_SECONDS, () => {
+ try {Mainloop.source_remove(this._iconTimeoutId);} catch(e) {}
+ this._iconTimeoutId = null;
+ this.setIcon();
+ });
+ } else {
+ // if we have an active player and want to change the icon, change it immediately
+ if (this._playerIcon[1]) {
+ //~ logDebug("CHANGE the icon !!! "+this._playerIcon[0]);
+ if (this._playerIcon[0] != this.oldPlayerIcon0 || !this._iconTimeoutId) {
+ //~ logDebug("CHANGE the icon !!! "+this._playerIcon[0]);
+ this.set_applet_icon_path(this._playerIcon[0]);
+ this.oldPlayerIcon0 = this._playerIcon[0];
+ }
+ } else {
+ //~ logDebug("DON'T change the icon !!!");
+ if (this._playerIcon[0] != this.oldPlayerIcon0 || !this._iconTimeoutId) {
+ this.set_applet_icon_symbolic_name(this._playerIcon[0]);
+ this.oldPlayerIcon0 = this._playerIcon[0];
+ }
+ }
+ }
+ } else {
+ // if we have no active player show the output icon
+ this.set_applet_icon_symbolic_name(this._outputIcon);
+ }
+ this.volume_near_icon()
+ }
+
+ set_applet_icon_path (icon_path) {
+ this._ensureIcon();
+
+ try {
+ //~ if (this.cover) {
+ //~ this._applet_icon.set_gicon(this.cover);
+ //~ this._applet_icon.set_icon_type(St.IconType.FULLCOLOR);
+ //~ this._setStyle();
+ //~ return
+ //~ }
+ let file = Gio.file_new_for_path(icon_path);
+ this._applet_icon.set_gicon(new Gio.FileIcon({ file: file }));
+ this._applet_icon.set_icon_type(St.IconType.FULLCOLOR);
+ this._setStyle();
+ } catch (e) {
+ // global.log(e);
+ }
+ }
+
+ loopArt() {
+ if (!this._playerctl) {
+ if (this._loopArtId) {
+ try {Mainloop.source_remove(this._loopArtId);} catch(e) {}
+ this._loopArtId = null;
+ }
+ this._loopArtId = Mainloop.timeout_add_seconds(5, this.loopArt.bind(this));
+ return
+ }
+ let subProcess = Util.spawnCommandLineAsyncIO("bash -C %s/get_album_art.sh".format(PATH2SCRIPTS), Lang.bind(this, function(stdout, stderr, exitCode) {
+ if (exitCode === 0) {
+ this._trackCoverFile = "file://"+stdout;
+ let cover_path = decodeURIComponent(this._trackCoverFile);
+ cover_path = cover_path.replace("file://", "");
+ const file = Gio.File.new_for_path(cover_path);
+ try {
+ const fileInfo = file.query_info("standard::*,unix::uid",
+ Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
+ const size = fileInfo.get_size();
+ if (size > 0) {
+ this._icon_path = cover_path;
+ this.setAppletIcon(true, true);
+ } else {
+ this._icon_path = null;
+ this._trackCoverFile = null;
+ }
+ } catch(e) {
+ this._icon_path = null;
+ this._trackCoverFile = null;
+ }
+ } else {
+ this._trackCoverFile = null;
+ }
+ subProcess.send_signal(9);
+ }));
+ if (this._loopArtId) {
+ try {Mainloop.source_remove(this._loopArtId);} catch(e) {}
+ this._loopArtId = null;
+ }
+ this._loopArtId = Mainloop.timeout_add_seconds(5, this.loopArt.bind(this))
+ }
+
+ setAppletIcon(player, path) {
+ //~ log("setAppletIcon path:"+path, true);
+ if (this.volume === "0%") {
+ this.setIcon("audio-volume-muted-symbolic", "player-name");
+ return
+ }
+ if (path != null) {
+ if (path === true) {
+ // Restore the icon path from the saved path.
+ path = this._icon_path;
+ } else {
+ this._icon_path = path;
+ }
+ } else {
+ // This track has no art, erase the saved path.
+ this._icon_path = null;
+ path = null;
+ }
+
+ if (this.showalbum) {
+ if (path && player && (player === true || player._playerStatus == "Playing")) {
+ this.setIcon(path, "player-path");
+ } else {
+ if (this.showMicMutedOnIcon && (!this.mute_in_switch || this.mute_in_switch.state))
+ this.setIcon("media-optical-cd-audio-with-mic-disabled", "player-name");
+ else if (this.showMicUnmutedOnIcon && (this.mute_in_switch && !this.mute_in_switch.state))
+ this.setIcon("media-optical-cd-audio-with-mic-enabled", "player-name");
+ else
+ this.setIcon("media-optical-cd-audio", "player-name");
+ }
+ }
+ else {
+ if (this.showMicMutedOnIcon && (!this.mute_in_switch || this.mute_in_switch.state))
+ this.setIcon("audio-x-generic-with-mic-disabled", "player-name");
+ else if (this.showMicUnmutedOnIcon && (this.mute_in_switch && !this.mute_in_switch.state))
+ this.setIcon("audio-x-generic-with-mic-enabled", "player-name");
+ else
+ this.setIcon("audio-x-generic", "player-name");
+ }
+ }
+
+ setAppletText(player) {
+ this.title_text = "";
+ if (this.isHorizontal && this.showtrack && player && player._playerStatus == "Playing") {
+ if (player._artist == _("Unknown Artist")) { // should it be translated?
+ this.title_text = player._title;
+ }
+ else {
+ this.title_text = player._title + ' - ' + player._artist;
+ }
+ const glyphs = Util.splitByGlyph(this.title_text);
+ if (glyphs.length > this.truncatetext) {
+ this.title_text = glyphs.slice(0, this.truncatetext - 3).join("") + "...";
+ }
+ }
+ //this.set_applet_label(this.title_text);
+ //~ log("setAppletText: this.title_text:\n"+this.title_text, true)
+ }
+
+ setAppletTextIcon(player, icon) {
+ this.player = player;
+ if (player && player._owner != this._activePlayer)
+ return;
+ this.setAppletIcon(player, icon);
+ this.setAppletText(player);
+ this.setAppletTooltip();
+ }
+
+ setAppletTooltip() {
+ let tooltips = [];
+ if (this.tooltipShowVolume) {
+ tooltips.push(_("Volume") + ": " + this.volume);
+ }
+ if (this.player && this.player._owner == this._activePlayer) {
+ if (this.tooltipShowPlayer) {
+ tooltips.push(this.player._name + " - " + _(this.player._playerStatus));
+ }
+ if (this.tooltipShowArtistTitle) {
+ if (this.player._artist != _("Unknown Artist")) {
+ tooltips.push(this.player._artist);
+ }
+ if (this._title != _("Unknown Title")) {
+ tooltips.push(this.player._title);
+ }
+ }
+ }
+ if (!this._playerctl) {
+ tooltips.push(_("The 'playerctl' package is required!"));
+ tooltips.push(_("Please select 'Install playerctl' in this menu"));
+ }
+
+ this.set_applet_tooltip(tooltips.join("\n"));
+ this.volume_near_icon();
+ }
+
+ _isInstance(busName) {
+ // MPRIS instances are in the form
+ // org.mpris.MediaPlayer2.name.instanceXXXX
+ // ...except for VLC, which to this day uses
+ // org.mpris.MediaPlayer2.name-XXXX
+ return busName.split(".").length > 4 ||
+ /^org\.mpris\.MediaPlayer2\.vlc-\d+$/.test(busName);
+ }
+
+ _addPlayer(busName, owner) {
+ if (this._players[owner]) {
+ let prevName = this._players[owner]._busName;
+ // HAVE: ADDING: ACTION:
+ // master master reject, cannot happen
+ // master instance upgrade to instance
+ // instance master reject, duplicate
+ // instance instance reject, cannot happen
+ if (this._isInstance(busName) && !this._isInstance(prevName))
+ this._players[owner]._busName = busName;
+ else
+ return;
+ } else if (owner) {
+ let player = new Player(this, busName, owner);
+
+ // Add the player to the list of active players in GUI.
+ // We don't have the org.mpris.MediaPlayer2 interface set up at this point,
+ // add the player's busName as a placeholder until we can get its Identity.
+ let item = new PopupMenu.PopupMenuItem(busName);
+ item.activate = () => this._switchPlayer(player._owner);
+ this._chooseActivePlayerItem.menu.addMenuItem(item);
+
+ this._players[owner] = player;
+ this._playerItems.push({ player: player, item: item });
+
+ this._changeActivePlayer(owner);
+ this._updatePlayerMenuItems();
+ this.setAppletTextIcon();
+ }
+ }
+
+ _switchPlayer(owner) {
+ if (this._players[owner]) {
+ // The player exists, switch to it
+ this._changeActivePlayer(owner);
+ this._updatePlayerMenuItems();
+ this.setAppletTextIcon();
+ } else {
+ // The player doesn't seem to exist. Remove it from the players list
+ this._removePlayerItem(owner);
+ this._updatePlayerMenuItems();
+ }
+ }
+
+ _switchToNextPlayer() {
+ if (this._playerItems.length <= 1 || !this._activePlayer) return;
+
+ for (let i = 0, l = this._playerItems.length; i < l; ++i) {
+ let playerItem = this._playerItems[i];
+ if (playerItem.player._owner === this._activePlayer) {
+ let selected = (i+1)%l;
+ this._switchPlayer(this._playerItems[selected].player._owner);
+ return
+ }
+ }
+ }
+
+ _removePlayerItem(owner) {
+ // Remove the player from the player switching list
+ for (let i = 0, l = this._playerItems.length; i < l; ++i) {
+ let playerItem = this._playerItems[i];
+ if (playerItem.player._owner === owner) {
+ playerItem.item.destroy();
+ this._playerItems.splice(i, 1);
+ break;
+ }
+ }
+ }
+
+ _removePlayer(busName, owner) {
+ if (this._players[owner] && this._players[owner]._busName == busName) {
+ this._removePlayerItem(owner);
+
+ this._players[owner].destroy();
+ delete this._players[owner];
+
+ if (this._activePlayer == owner) {
+ // set _activePlayer to null if we have none now, or to the first value in the players list
+ this._activePlayer = null;
+ for (let i in this._players) {
+ this._changeActivePlayer(i);
+ break;
+ }
+ }
+ this._updatePlayerMenuItems();
+ this.setAppletTextIcon();
+ }
+ }
+
+ _changePlayerOwner(busName, oldOwner, newOwner) {
+ if (this._players[oldOwner] && busName == this._players[oldOwner]._busName) {
+ this._players[newOwner] = this._players[oldOwner];
+ this._players[newOwner]._owner = newOwner;
+ delete this._players[oldOwner];
+ if (this._activePlayer == oldOwner)
+ this._activePlayer = newOwner;
+ }
+ }
+
+ // will be called by an instance of #Player
+ passDesktopEntry(entry) {
+ if (entry == null) return;
+ // do we know already this player?
+ for (let i = 0, l = this._knownPlayers.length; i < l; ++i) {
+ if (this._knownPlayers[i] === entry)
+ return;
+ }
+ // No, save it to _knownPlayers and update player list
+ this._knownPlayers.push(entry);
+ this._knownPlayers.save();
+ this._updateLaunchPlayer();
+ }
+
+ _showFixedElements() {
+ // The launch player list
+ this._launchPlayerItem = new PopupMenu.PopupSubMenuMenuItem(_("Launch player"));
+ this.menu.addMenuItem(this._launchPlayerItem);
+ this._updateLaunchPlayer();
+
+ // The list to use when switching between active players
+ this._chooseActivePlayerItem = new PopupMenu.PopupSubMenuMenuItem(_("Choose player controls"));
+ this._chooseActivePlayerItem.actor.hide();
+ this._chooseActivePlayerItemActorIsHidden = true;
+ this.menu.addMenuItem(this._chooseActivePlayerItem);
+
+ // between these two separators will be the player MenuSection (position 3)
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+ this._outputVolumeSection = new VolumeSlider(this, null, _("Volume"), null);
+ this._outputVolumeSection.connect("values-changed", (...args) => this._outputValuesChanged(...args));
+
+ this.menu.addMenuItem(this._outputVolumeSection);
+ this.menu.addMenuItem(this._inputVolumeSection);
+
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+ this.menu.addSettingsAction(_("Sound Settings"), "sound");
+
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+ // button Reload this applet
+ let _reload_button = new PopupMenu.PopupIconMenuItem(_("Reload this applet"), "restart", St.IconType.SYMBOLIC);
+ _reload_button.connect("activate", (event) => this._on_reload_this_applet_pressed());
+ this.menu.addMenuItem(_reload_button);
+
+ // button "remove_soundATcinnamonDOTorg"
+ if (this.soundATcinnamonDOTorg_is_loaded) {
+ let _remove_soundATcinnamonDOTorg_button = new PopupMenu.PopupIconMenuItem(_("Remove sound applet"), "edit-delete", St.IconType.SYMBOLIC);
+ _remove_soundATcinnamonDOTorg_button.connect("activate", (event) => {
+ this._on_remove_soundATcinnamonDOTorg_from_panels()
+ });
+ this.menu.addMenuItem(_remove_soundATcinnamonDOTorg_button);
+ }
+
+ //button Install playerctl (when it isn't installed)
+ if (this._playerctl === null) {
+ let _install_playerctl_button = new PopupMenu.PopupIconMenuItem(_("Install playerctl"), "system-software-install", St.IconType.SYMBOLIC);
+ _install_playerctl_button.connect("activate", (event) => {
+ Util.spawnCommandLine("bash -C '%s/install_playerctl.sh'".format(PATH2SCRIPTS));
+ this._on_reload_this_applet_pressed();
+ });
+ this.menu.addMenuItem(_install_playerctl_button);
+ }
+ }
+
+ _updateLaunchPlayer() {
+ let availablePlayers = [];
+
+ let appsys = Cinnamon.AppSystem.get_default();
+ //_knownPlayers is an array containing the paths of desktop files
+ for (let i = 0, l = this._knownPlayers.length; i < l; ++i) {
+ let app = appsys.lookup_app(this._knownPlayers[i] + ".desktop");
+ if (app)
+ availablePlayers.push(app);
+ }
+
+ this._launchPlayerItem.menu.removeAll();
+
+ if (availablePlayers.length > 0) {
+ for (var p = 0; p < availablePlayers.length; p++) {
+ let playerApp = availablePlayers[p];
+ let menuItem = new MediaPlayerLauncher(playerApp, this._launchPlayerItem.menu);
+ this._launchPlayerItem.menu.addMenuItem(menuItem);
+ }
+ }
+
+ if (!this.playerControl || !availablePlayers.length) {
+ this._launchPlayerItem.actor.hide();
+ this._launchPlayerItemActorIsHidden = true;
+ }
+ }
+
+ _updatePlayerMenuItems() {
+ let names = [];
+
+ if (this.playerControl && this._activePlayer) {
+ this._launchPlayerItem.actor.show();
+ this._launchPlayerItemActorIsHidden = false;
+ this._chooseActivePlayerItem.actor.show();
+ this._chooseActivePlayerItemActorIsHidden = false;
+
+ // Show a dot on the active player in the switching menu
+ for (let i = 0, l = this._playerItems.length; i < l; ++i) {
+ let playerItem = this._playerItems[i];
+
+ if (!this.avoidTwice || (this.avoidTwice && names.indexOf(playerItem.player._name) < 0)) {
+ playerItem.item.setLabel(playerItem.player._name);
+ playerItem.item.setShowDot(playerItem.player._owner === this._activePlayer);
+ names.push(playerItem.player._name);
+ }
+ else {
+ this._removePlayerItem(playerItem.player._owner);
+ }
+ }
+
+ // Hide the switching menu if we only have at most one active player
+ if (this._chooseActivePlayerItem.menu.numMenuItems <= 1) {
+ this._chooseActivePlayerItem.actor.hide();
+ this._chooseActivePlayerItemActorIsHidden = true;
+ }
+ } else {
+ if (this.playerControl && this._launchPlayerItem.menu.numMenuItems) {
+ this._launchPlayerItem.actor.show();
+ this._launchPlayerItemActorIsHidden = false;
+ } else {
+ this._launchPlayerItem.actor.hide();
+ this._launchPlayerItemActorIsHidden = true;
+ this._chooseActivePlayerItem.actor.hide();
+ this._chooseActivePlayerItemActorIsHidden = true;
+ }
+ }
+ }
+
+ _changeActivePlayer(player) {
+ if (this._activePlayer)
+ this.menu.box.remove_actor(this._players[this._activePlayer].actor);
+
+ this._activePlayer = player;
+ if (this.playerControl && this._activePlayer != null) {
+ let menuItem = this._players[player];
+ this.menu.addMenuItem(menuItem, 2);
+ }
+
+ this._updatePlayerMenuItems();
+ }
+
+ _notifyVolumeChange(stream) {
+ if (this.volumeSoundEnabled)
+ Main.soundManager.play("volume");
+ }
+
+ _mutedChanged(object, param_spec, property) {
+ if (property == "_output") {
+ this.mute_out_switch.setToggleState(this._output.is_muted);
+ } else if (property == "_input") {
+ this.mute_in_switch.setToggleState(this._input.is_muted);
+ this._volumeChange(null);
+ }
+ }
+
+ _theme_set() {
+ this._on_reload_this_applet_pressed();
+ }
+
+ _outputValuesChanged(actor, iconName, percentage) {
+ this.setIcon(iconName, "output");
+ this.mute_out_switch.setIconSymbolicName(iconName);
+ this.volume = percentage;
+ this.setAppletTooltip();
+
+ if (!this.themeNode) {
+ this.themeNode = this.actor.get_theme_node();
+ }
+ let defaultColor = this.themeNode.get_foreground_color();
+ let color = "rgba(" + defaultColor.red + "," + defaultColor.green + "," + defaultColor.blue + "," + defaultColor.alpha + ")";
+
+ let changeColor = false;
+ if (this.adaptColor) {
+ let pc = Math.round(percentage.split("%")[0]);
+ if (pc > 130) {
+ color = this.color131_150; //Default is "red";
+ changeColor = true;
+ }
+ else if (pc > 115) {
+ color = this.color116_130; //Default is "orange";
+ changeColor = true;
+ }
+ else if (pc > 100) {
+ color = this.color101_115; //Default is "yellow";
+ changeColor = true;
+ }
+ }
+ let _style = "color: %s;".format(color);
+
+ try {
+ this.actor.style = _style;
+
+ if (changeColor) {
+ if (this._outputVolumeSection && this._outputVolumeSection.icon)
+ this._outputVolumeSection.icon.style = _style;
+ //~ this._outputVolumeSection.style = _style;
+ } else {
+ if (this._inputVolumeSection && this._inputVolumeSection.icon)
+ this._outputVolumeSection.icon.style = this._inputVolumeSection.icon.style
+ }
+ } catch(e) {logError("Problem changing color!!!: "+e)}
+ }
+
+ _inputValuesChanged(actor, iconName, percentage) {
+ this.mute_in_switch.setIconSymbolicName(iconName);
+ this.mic_level = percentage;
+ }
+
+ _onControlStateChanged() {
+ if (this._control.get_state() == Cvc.MixerControlState.READY) {
+ this._readOutput();
+ this._readInput();
+ this.actor.show();
+ } else {
+ this.actor.hide();
+ }
+ }
+
+ _readOutput() {
+ if (this._outputMutedId) {
+ this._output.disconnect(this._outputMutedId);
+ this._outputMutedId = 0;
+ }
+ this._output = this._control.get_default_sink();
+ if (this._output) {
+ this._outputVolumeSection.connectWithStream(this._output);
+ this._outputMutedId = this._output.connect("notify::is-muted", (...args) => this._mutedChanged(...args, "_output"));
+ this._mutedChanged(null, null, "_output");
+ } else {
+ this.setIcon("audio-volume-muted-symbolic", "output");
+ }
+ }
+
+ _readInput() {
+ if (this._inputMutedId) {
+ this._input.disconnect(this._inputMutedId);
+ this._inputMutedId = 0;
+ }
+ this._input = this._control.get_default_source();
+ if (this._input) {
+ this._inputVolumeSection.connectWithStream(this._input);
+ this._inputMutedId = this._input.connect("notify::is-muted", (...args) => this._mutedChanged(...args, "_input"));
+ this._mutedChanged(null, null, "_input");
+ this._inputSection.actor.show(); // Added
+ } else {
+ this._inputSection.actor.hide();
+ }
+ }
+
+ _onDeviceAdded(control, id, type) {
+ let device = this._control["lookup_" + type + "_id"](id);
+
+ let item = new PopupMenu.PopupMenuItem(device.description);
+ item.activate = () => this._control["change_" + type](device);
+
+ let bin = new St.Bin({ x_align: St.Align.END, style_class: "popup-inactive-menu-item" });
+ let label = new St.Label({ text: device.origin });
+ bin.add_actor(label);
+ try {
+ item.addActor(bin, { expand: true, span: -1, align: St.Align.END });
+ } catch(e) {logError("Unable to add actor bin to item!: "+e)}
+
+ let selectItem = this["_select" + type[0].toUpperCase() + type.slice(1) + "DeviceItem"];
+ selectItem.menu.addMenuItem(item);
+ // show the menu if we have more than two devices
+ if (selectItem.menu.numMenuItems > 1)
+ selectItem.actor.show();
+
+ this._devices.push({ id: id, type: type, item: item });
+ }
+
+ _onDeviceRemoved(control, id, type) {
+ for (let i = 0, l = this._devices.length; i < l; ++i) {
+ if (this._devices[i].type === type && this._devices[i].id === id) {
+ let device = this._devices[i];
+ if (device.item)
+ device.item.destroy();
+
+ // hide submenu if showing them is unnecessary
+ let selectItem = this["_select" + type[0].toUpperCase() + type.slice(1) + "DeviceItem"];
+ if (selectItem.menu.numMenuItems <= 1)
+ selectItem.actor.hide();
+
+ this._devices.splice(i, 1);
+ break;
+ }
+ }
+ }
+
+ _onDeviceUpdate(control, id, type) {
+ this["_read" + type[0].toUpperCase() + type.slice(1)]();
+
+ for (let i = 0, l = this._devices.length; i < l; ++i) {
+ if (this._devices[i].type === type)
+ this._devices[i].item.setShowDot(id === this._devices[i].id);
+ }
+ }
+
+ _onStreamAdded(control, id) {
+ //~ logDebug("_onStreamAdded. control: "+control+" ; id: "+id);
+ let stream = this._control.lookup_stream_id(id);
+ let appId = stream.application_id;
+
+ if (stream.is_virtual || appId === "org.freedesktop.libcanberra") {
+ // sort out unwanted streams
+ return;
+ }
+
+ if (stream instanceof Cvc.MixerSinkInput) {
+ // for sink inputs, add a menuitem to the application submenu
+ let item = new StreamMenuSection(this, stream);
+ this._outputApplicationsMenu.menu.addMenuItem(item);
+ this._outputApplicationsMenu.actor.show();
+ this._streams.push({ id: id, type: "SinkInput", item: item });
+ } else if (stream instanceof Cvc.MixerSourceOutput) {
+ // for source outputs, only show the input section
+ this._streams.push({ id: id, type: "SourceOutput" });
+ if (this._recordingAppsNum++ === 0) {
+ this._inputSection.actor.show();
+ this.mute_in_switch.actor.show();
+ run_playerctld();
+ }
+ }
+ }
+
+ _onStreamRemoved(control, id) {
+ //~ logDebug("_onStreamRemoved. control: "+control+" ; id: "+id);
+ for (let i = 0, l = this._streams.length; i < l; ++i) {
+ if (this._streams[i].id === id) {
+ let stream = this._streams[i];
+ if (stream.item) {
+ stream.item.destroy();
+ }
+
+ // hide submenus or sections if showing them is unnecessary
+ if (stream.type === "SinkInput") {
+ if (this._outputApplicationsMenu.menu.numMenuItems === 0)
+ this._outputApplicationsMenu.actor.hide();
+ } else if (stream.type === "SourceOutput") {
+ if (--this._recordingAppsNum === 0) {
+ this._inputSection.actor.hide();
+ this.mute_in_switch.actor.hide();
+ }
+
+ if (this.alwaysCanChangeMic) {
+ this._inputSection.actor.show();
+ this.mute_in_switch.actor.show();
+ }
+ //~ kill_playerctld();
+ }
+ if (this._seeker)
+ this._seeker.destroy();
+ this._seeker = null;
+ kill_playerctld();
+ this._streams.splice(i, 1);
+ break;
+ }
+ }
+ }
+
+ registerSystrayIcons() {
+ for (let i = 0; i < players_with_seek_support.length; i++) {
+ Main.systrayManager.registerTrayIconReplacement(players_with_seek_support[i], this.metadata.uuid);
+ }
+ for (let i = 0; i < players_without_seek_support.length; i++) {
+ Main.systrayManager.registerTrayIconReplacement(players_without_seek_support[i], this.metadata.uuid);
+ }
+ }
+
+ unregisterSystrayIcons() {
+ Main.systrayManager.unregisterTrayIconReplacement(this.metadata.uuid);
+ }
+
+ _on_reload_this_applet_pressed() {
+ kill_playerctld();
+ // Reload this applet
+ Extension.reloadExtension(UUID, Extension.Type.APPLET);
+ }
+
+ _onSetApmlificationPressed() {
+ let command = "cinnamon-settings sound -t 4";
+ Util.spawnCommandLine(command);
+ }
+
+ volume_near_icon() {
+ let label = "";
+ if (this.showVolumeLevelNearIcon) {
+ //~ this._applet_label.set_text(""+this.volume+ (this.title_text.length>0) ? " - "+this.title_text : "");
+ label = ""+this.volume;
+ if (this.title_text.length>0)
+ label += " - "+this.title_text;
+ this.set_applet_label(label);
+ } else {
+ //~ this._applet_label.set_text((this.title_text.length>0) ? ""+this.title_text : "");
+ if (this.title_text.length>0)
+ label = ""+this.title_text;
+ this.set_applet_label(label);
+ }
+ this.hide_applet_label(label.length === 0);
+ }
+
+ _reset_colors() {
+ this.color101_115 = "yellow";
+ this.color116_130 = "orange";
+ this.color131_150 = "red";
+ this._on_sound_settings_change()
+ }
+
+ _set_shortcuts_as_default() {
+ const schema = "org.cinnamon.desktop.keybindings.media-keys";
+ const s = new Gio.Settings({ schema_id: schema });
+
+ const pause_on_off = s.get_strv("pause");
+ this.pause_on_off = pause_on_off.join("::");
+
+ const audio_stop = s.get_strv("stop");
+ this.audio_stop = audio_stop.join("::");
+
+ const volume_mute = s.get_strv("volume-mute");
+ this.volume_mute = volume_mute.join("::");
+
+ const volume_up = s.get_strv("volume-up");
+ this.volume_up = volume_up.join("::");
+
+ const volume_down = s.get_strv("volume-down");
+ this.volume_down = volume_down.join("::");
+
+ const audio_next = s.get_strv("next");
+ this.audio_next = audio_next.join("::");
+
+ const audio_prev = s.get_strv("previous");
+ this.audio_prev = audio_prev.join("::");
+ }
+
+ get _playerctl() {
+ return GLib.find_program_in_path("playerctl");
+ }
+}
+
+function main(metadata, orientation, panel_height, instanceId) {
+ return new Sound150Applet(metadata, orientation, panel_height, instanceId);
+}
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-symbolic.svg
new file mode 100644
index 00000000000..94880099f6c
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-symbolic.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..ef38578cea8
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-with-mic-disabled-symbolic.svg
@@ -0,0 +1,102 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..26cbfdee656
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-high-with-mic-enabled-symbolic.svg
@@ -0,0 +1,105 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-symbolic.svg
new file mode 100644
index 00000000000..f5aa2a05dda
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-symbolic.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..80941d09877
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-with-mic-disabled-symbolic.svg
@@ -0,0 +1,104 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..3abd87fa0e6
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-low-with-mic-enabled-symbolic.svg
@@ -0,0 +1,109 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-symbolic.svg
new file mode 100644
index 00000000000..200ba430675
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-symbolic.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..5eec7d5ffe0
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-with-mic-disabled-symbolic.svg
@@ -0,0 +1,103 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..0525323f943
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-medium-with-mic-enabled-symbolic.svg
@@ -0,0 +1,111 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-symbolic.svg
new file mode 100644
index 00000000000..7084650fc4b
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-symbolic.svg
@@ -0,0 +1,39 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..d060a568d75
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-with-mic-disabled-symbolic.svg
@@ -0,0 +1,106 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..a08dfe54134
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-muted-with-mic-enabled-symbolic.svg
@@ -0,0 +1,109 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-symbolic.svg
new file mode 100644
index 00000000000..53e4e01811e
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-symbolic.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..1203ad1e200
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-with-mic-disabled-symbolic.svg
@@ -0,0 +1,102 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..b8f1f2eb495
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-volume-overamplified-with-mic-enabled-symbolic.svg
@@ -0,0 +1,105 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-symbolic.svg
new file mode 100644
index 00000000000..0320ff2c244
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-symbolic.svg
@@ -0,0 +1,124 @@
+
+
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..9e04b98ea2d
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-with-mic-disabled-symbolic.svg
@@ -0,0 +1,128 @@
+
+
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..f059387cf4c
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/audio-x-generic-with-mic-enabled-symbolic.svg
@@ -0,0 +1,131 @@
+
+
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/easyeffects-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/easyeffects-symbolic.svg
new file mode 100644
index 00000000000..35973b02992
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/easyeffects-symbolic.svg
@@ -0,0 +1,88 @@
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/easyeffects.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/easyeffects.svg
new file mode 100644
index 00000000000..8a522395af5
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/easyeffects.svg
@@ -0,0 +1,22 @@
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/highlights.css b/sound150@claudiux/files/sound150@claudiux/6.4/icons/highlights.css
new file mode 100644
index 00000000000..362fb0bf33a
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/highlights.css
@@ -0,0 +1,36 @@
+/*
+* Change only colors, do not add more class, order or remove
+* also dont change selectors definition
+*/
+
+.base {
+ fill: #000000;
+}
+
+.success {
+ fill: #009909;
+}
+
+.warning {
+ fill: #FF1990;
+}
+
+.error {
+ fill: #0099E6;
+}
+
+.dark .base {
+ fill: #EBEBEB;
+}
+
+.dark .success {
+ fill: #0ABF15;
+}
+
+.dark .warning {
+ fill: #FF1990;
+}
+
+.dark .error {
+ fill: #0099E6;
+}
\ No newline at end of file
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-symbolic.svg
new file mode 100644
index 00000000000..674bc84742f
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-symbolic.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-with-mic-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-with-mic-disabled-symbolic.svg
new file mode 100644
index 00000000000..f9c50dbe215
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-with-mic-disabled-symbolic.svg
@@ -0,0 +1,95 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-with-mic-enabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-with-mic-enabled-symbolic.svg
new file mode 100644
index 00000000000..b6db916c77e
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/media-optical-cd-audio-with-mic-enabled-symbolic.svg
@@ -0,0 +1,98 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-disabled-symbolic.svg
new file mode 100644
index 00000000000..4adefa72433
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-disabled-symbolic.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-hardware-disabled-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-hardware-disabled-symbolic.svg
new file mode 100644
index 00000000000..2ae6f59c96a
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-hardware-disabled-symbolic.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-high-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-high-symbolic.svg
new file mode 100644
index 00000000000..f85a5896ad3
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-high-symbolic.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-low-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-low-symbolic.svg
new file mode 100644
index 00000000000..63bdb864201
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-low-symbolic.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-medium-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-medium-symbolic.svg
new file mode 100644
index 00000000000..c9924ca7e29
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-medium-symbolic.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-muted-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-muted-symbolic.svg
new file mode 100644
index 00000000000..ac02609a05a
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-muted-symbolic.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-overamplified-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-overamplified-symbolic.svg
new file mode 100644
index 00000000000..f85a5896ad3
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/microphone-sensitivity-overamplified-symbolic.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/pulseeffects-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/pulseeffects-symbolic.svg
new file mode 100755
index 00000000000..4d6d3852256
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/pulseeffects-symbolic.svg
@@ -0,0 +1,65 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/pulseeffects.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/pulseeffects.svg
new file mode 100644
index 00000000000..8926bdee4fa
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/pulseeffects.svg
@@ -0,0 +1,24 @@
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/icons/restart-symbolic.svg b/sound150@claudiux/files/sound150@claudiux/6.4/icons/restart-symbolic.svg
new file mode 100644
index 00000000000..4ef4b7276f9
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/icons/restart-symbolic.svg
@@ -0,0 +1,152 @@
+
+
+
+
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/lib/htmlEncodeDecode.js b/sound150@claudiux/files/sound150@claudiux/6.4/lib/htmlEncodeDecode.js
new file mode 100644
index 00000000000..69692064781
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/lib/htmlEncodeDecode.js
@@ -0,0 +1,345 @@
+/*! https://mths.be/he v1.2.0 by @mathias | MIT license */
+;(function(root) {
+
+ // Detect free variables `exports`.
+ var freeExports = typeof exports == 'object' && exports;
+
+ // Detect free variable `module`.
+ var freeModule = typeof module == 'object' && module &&
+ module.exports == freeExports && module;
+
+ // Detect free variable `global`, from Node.js or Browserified code,
+ // and use it as `root`.
+ //~ var freeGlobal = typeof global == 'object' && global;
+ //~ if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
+ //~ root = freeGlobal;
+ //~ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // All astral symbols.
+ var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
+ // All ASCII symbols (not just printable ASCII) except those listed in the
+ // first column of the overrides table.
+ // https://html.spec.whatwg.org/multipage/syntax.html#table-charref-overrides
+ var regexAsciiWhitelist = /[\x01-\x7F]/g;
+ // All BMP symbols that are not ASCII newlines, printable ASCII symbols, or
+ // code points listed in the first column of the overrides table on
+ // https://html.spec.whatwg.org/multipage/syntax.html#table-charref-overrides.
+ var regexBmpWhitelist = /[\x01-\t\x0B\f\x0E-\x1F\x7F\x81\x8D\x8F\x90\x9D\xA0-\uFFFF]/g;
+
+ var regexEncodeNonAscii = /<\u20D2|=\u20E5|>\u20D2|\u205F\u200A|\u219D\u0338|\u2202\u0338|\u2220\u20D2|\u2229\uFE00|\u222A\uFE00|\u223C\u20D2|\u223D\u0331|\u223E\u0333|\u2242\u0338|\u224B\u0338|\u224D\u20D2|\u224E\u0338|\u224F\u0338|\u2250\u0338|\u2261\u20E5|\u2264\u20D2|\u2265\u20D2|\u2266\u0338|\u2267\u0338|\u2268\uFE00|\u2269\uFE00|\u226A\u0338|\u226A\u20D2|\u226B\u0338|\u226B\u20D2|\u227F\u0338|\u2282\u20D2|\u2283\u20D2|\u228A\uFE00|\u228B\uFE00|\u228F\u0338|\u2290\u0338|\u2293\uFE00|\u2294\uFE00|\u22B4\u20D2|\u22B5\u20D2|\u22D8\u0338|\u22D9\u0338|\u22DA\uFE00|\u22DB\uFE00|\u22F5\u0338|\u22F9\u0338|\u2933\u0338|\u29CF\u0338|\u29D0\u0338|\u2A6D\u0338|\u2A70\u0338|\u2A7D\u0338|\u2A7E\u0338|\u2AA1\u0338|\u2AA2\u0338|\u2AAC\uFE00|\u2AAD\uFE00|\u2AAF\u0338|\u2AB0\u0338|\u2AC5\u0338|\u2AC6\u0338|\u2ACB\uFE00|\u2ACC\uFE00|\u2AFD\u20E5|[\xA0-\u0113\u0116-\u0122\u0124-\u012B\u012E-\u014D\u0150-\u017E\u0192\u01B5\u01F5\u0237\u02C6\u02C7\u02D8-\u02DD\u0311\u0391-\u03A1\u03A3-\u03A9\u03B1-\u03C9\u03D1\u03D2\u03D5\u03D6\u03DC\u03DD\u03F0\u03F1\u03F5\u03F6\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E\u045F\u2002-\u2005\u2007-\u2010\u2013-\u2016\u2018-\u201A\u201C-\u201E\u2020-\u2022\u2025\u2026\u2030-\u2035\u2039\u203A\u203E\u2041\u2043\u2044\u204F\u2057\u205F-\u2063\u20AC\u20DB\u20DC\u2102\u2105\u210A-\u2113\u2115-\u211E\u2122\u2124\u2127-\u2129\u212C\u212D\u212F-\u2131\u2133-\u2138\u2145-\u2148\u2153-\u215E\u2190-\u219B\u219D-\u21A7\u21A9-\u21AE\u21B0-\u21B3\u21B5-\u21B7\u21BA-\u21DB\u21DD\u21E4\u21E5\u21F5\u21FD-\u2205\u2207-\u2209\u220B\u220C\u220F-\u2214\u2216-\u2218\u221A\u221D-\u2238\u223A-\u2257\u2259\u225A\u225C\u225F-\u2262\u2264-\u228B\u228D-\u229B\u229D-\u22A5\u22A7-\u22B0\u22B2-\u22BB\u22BD-\u22DB\u22DE-\u22E3\u22E6-\u22F7\u22F9-\u22FE\u2305\u2306\u2308-\u2310\u2312\u2313\u2315\u2316\u231C-\u231F\u2322\u2323\u232D\u232E\u2336\u233D\u233F\u237C\u23B0\u23B1\u23B4-\u23B6\u23DC-\u23DF\u23E2\u23E7\u2423\u24C8\u2500\u2502\u250C\u2510\u2514\u2518\u251C\u2524\u252C\u2534\u253C\u2550-\u256C\u2580\u2584\u2588\u2591-\u2593\u25A1\u25AA\u25AB\u25AD\u25AE\u25B1\u25B3-\u25B5\u25B8\u25B9\u25BD-\u25BF\u25C2\u25C3\u25CA\u25CB\u25EC\u25EF\u25F8-\u25FC\u2605\u2606\u260E\u2640\u2642\u2660\u2663\u2665\u2666\u266A\u266D-\u266F\u2713\u2717\u2720\u2736\u2758\u2772\u2773\u27C8\u27C9\u27E6-\u27ED\u27F5-\u27FA\u27FC\u27FF\u2902-\u2905\u290C-\u2913\u2916\u2919-\u2920\u2923-\u292A\u2933\u2935-\u2939\u293C\u293D\u2945\u2948-\u294B\u294E-\u2976\u2978\u2979\u297B-\u297F\u2985\u2986\u298B-\u2996\u299A\u299C\u299D\u29A4-\u29B7\u29B9\u29BB\u29BC\u29BE-\u29C5\u29C9\u29CD-\u29D0\u29DC-\u29DE\u29E3-\u29E5\u29EB\u29F4\u29F6\u2A00-\u2A02\u2A04\u2A06\u2A0C\u2A0D\u2A10-\u2A17\u2A22-\u2A27\u2A29\u2A2A\u2A2D-\u2A31\u2A33-\u2A3C\u2A3F\u2A40\u2A42-\u2A4D\u2A50\u2A53-\u2A58\u2A5A-\u2A5D\u2A5F\u2A66\u2A6A\u2A6D-\u2A75\u2A77-\u2A9A\u2A9D-\u2AA2\u2AA4-\u2AB0\u2AB3-\u2AC8\u2ACB\u2ACC\u2ACF-\u2ADB\u2AE4\u2AE6-\u2AE9\u2AEB-\u2AF3\u2AFD\uFB00-\uFB04]|\uD835[\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDCCF\uDD04\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDD6B]/g;
+ var encodeMap = {'\xAD':'shy','\u200C':'zwnj','\u200D':'zwj','\u200E':'lrm','\u2063':'ic','\u2062':'it','\u2061':'af','\u200F':'rlm','\u200B':'ZeroWidthSpace','\u2060':'NoBreak','\u0311':'DownBreve','\u20DB':'tdot','\u20DC':'DotDot','\t':'Tab','\n':'NewLine','\u2008':'puncsp','\u205F':'MediumSpace','\u2009':'thinsp','\u200A':'hairsp','\u2004':'emsp13','\u2002':'ensp','\u2005':'emsp14','\u2003':'emsp','\u2007':'numsp','\xA0':'nbsp','\u205F\u200A':'ThickSpace','\u203E':'oline','_':'lowbar','\u2010':'dash','\u2013':'ndash','\u2014':'mdash','\u2015':'horbar',',':'comma',';':'semi','\u204F':'bsemi',':':'colon','\u2A74':'Colone','!':'excl','\xA1':'iexcl','?':'quest','\xBF':'iquest','.':'period','\u2025':'nldr','\u2026':'mldr','\xB7':'middot','\'':'apos','\u2018':'lsquo','\u2019':'rsquo','\u201A':'sbquo','\u2039':'lsaquo','\u203A':'rsaquo','"':'quot','\u201C':'ldquo','\u201D':'rdquo','\u201E':'bdquo','\xAB':'laquo','\xBB':'raquo','(':'lpar',')':'rpar','[':'lsqb',']':'rsqb','{':'lcub','}':'rcub','\u2308':'lceil','\u2309':'rceil','\u230A':'lfloor','\u230B':'rfloor','\u2985':'lopar','\u2986':'ropar','\u298B':'lbrke','\u298C':'rbrke','\u298D':'lbrkslu','\u298E':'rbrksld','\u298F':'lbrksld','\u2990':'rbrkslu','\u2991':'langd','\u2992':'rangd','\u2993':'lparlt','\u2994':'rpargt','\u2995':'gtlPar','\u2996':'ltrPar','\u27E6':'lobrk','\u27E7':'robrk','\u27E8':'lang','\u27E9':'rang','\u27EA':'Lang','\u27EB':'Rang','\u27EC':'loang','\u27ED':'roang','\u2772':'lbbrk','\u2773':'rbbrk','\u2016':'Vert','\xA7':'sect','\xB6':'para','@':'commat','*':'ast','/':'sol','undefined':null,'&':'amp','#':'num','%':'percnt','\u2030':'permil','\u2031':'pertenk','\u2020':'dagger','\u2021':'Dagger','\u2022':'bull','\u2043':'hybull','\u2032':'prime','\u2033':'Prime','\u2034':'tprime','\u2057':'qprime','\u2035':'bprime','\u2041':'caret','`':'grave','\xB4':'acute','\u02DC':'tilde','^':'Hat','\xAF':'macr','\u02D8':'breve','\u02D9':'dot','\xA8':'die','\u02DA':'ring','\u02DD':'dblac','\xB8':'cedil','\u02DB':'ogon','\u02C6':'circ','\u02C7':'caron','\xB0':'deg','\xA9':'copy','\xAE':'reg','\u2117':'copysr','\u2118':'wp','\u211E':'rx','\u2127':'mho','\u2129':'iiota','\u2190':'larr','\u219A':'nlarr','\u2192':'rarr','\u219B':'nrarr','\u2191':'uarr','\u2193':'darr','\u2194':'harr','\u21AE':'nharr','\u2195':'varr','\u2196':'nwarr','\u2197':'nearr','\u2198':'searr','\u2199':'swarr','\u219D':'rarrw','\u219D\u0338':'nrarrw','\u219E':'Larr','\u219F':'Uarr','\u21A0':'Rarr','\u21A1':'Darr','\u21A2':'larrtl','\u21A3':'rarrtl','\u21A4':'mapstoleft','\u21A5':'mapstoup','\u21A6':'map','\u21A7':'mapstodown','\u21A9':'larrhk','\u21AA':'rarrhk','\u21AB':'larrlp','\u21AC':'rarrlp','\u21AD':'harrw','\u21B0':'lsh','\u21B1':'rsh','\u21B2':'ldsh','\u21B3':'rdsh','\u21B5':'crarr','\u21B6':'cularr','\u21B7':'curarr','\u21BA':'olarr','\u21BB':'orarr','\u21BC':'lharu','\u21BD':'lhard','\u21BE':'uharr','\u21BF':'uharl','\u21C0':'rharu','\u21C1':'rhard','\u21C2':'dharr','\u21C3':'dharl','\u21C4':'rlarr','\u21C5':'udarr','\u21C6':'lrarr','\u21C7':'llarr','\u21C8':'uuarr','\u21C9':'rrarr','\u21CA':'ddarr','\u21CB':'lrhar','\u21CC':'rlhar','\u21D0':'lArr','\u21CD':'nlArr','\u21D1':'uArr','\u21D2':'rArr','\u21CF':'nrArr','\u21D3':'dArr','\u21D4':'iff','\u21CE':'nhArr','\u21D5':'vArr','\u21D6':'nwArr','\u21D7':'neArr','\u21D8':'seArr','\u21D9':'swArr','\u21DA':'lAarr','\u21DB':'rAarr','\u21DD':'zigrarr','\u21E4':'larrb','\u21E5':'rarrb','\u21F5':'duarr','\u21FD':'loarr','\u21FE':'roarr','\u21FF':'hoarr','\u2200':'forall','\u2201':'comp','\u2202':'part','\u2202\u0338':'npart','\u2203':'exist','\u2204':'nexist','\u2205':'empty','\u2207':'Del','\u2208':'in','\u2209':'notin','\u220B':'ni','\u220C':'notni','\u03F6':'bepsi','\u220F':'prod','\u2210':'coprod','\u2211':'sum','+':'plus','\xB1':'pm','\xF7':'div','\xD7':'times','<':'lt','\u226E':'nlt','<\u20D2':'nvlt','=':'equals','\u2260':'ne','=\u20E5':'bne','\u2A75':'Equal','>':'gt','\u226F':'ngt','>\u20D2':'nvgt','\xAC':'not','|':'vert','\xA6':'brvbar','\u2212':'minus','\u2213':'mp','\u2214':'plusdo','\u2044':'frasl','\u2216':'setmn','\u2217':'lowast','\u2218':'compfn','\u221A':'Sqrt','\u221D':'prop','\u221E':'infin','\u221F':'angrt','\u2220':'ang','\u2220\u20D2':'nang','\u2221':'angmsd','\u2222':'angsph','\u2223':'mid','\u2224':'nmid','\u2225':'par','\u2226':'npar','\u2227':'and','\u2228':'or','\u2229':'cap','\u2229\uFE00':'caps','\u222A':'cup','\u222A\uFE00':'cups','\u222B':'int','\u222C':'Int','\u222D':'tint','\u2A0C':'qint','\u222E':'oint','\u222F':'Conint','\u2230':'Cconint','\u2231':'cwint','\u2232':'cwconint','\u2233':'awconint','\u2234':'there4','\u2235':'becaus','\u2236':'ratio','\u2237':'Colon','\u2238':'minusd','\u223A':'mDDot','\u223B':'homtht','\u223C':'sim','\u2241':'nsim','\u223C\u20D2':'nvsim','\u223D':'bsim','\u223D\u0331':'race','\u223E':'ac','\u223E\u0333':'acE','\u223F':'acd','\u2240':'wr','\u2242':'esim','\u2242\u0338':'nesim','\u2243':'sime','\u2244':'nsime','\u2245':'cong','\u2247':'ncong','\u2246':'simne','\u2248':'ap','\u2249':'nap','\u224A':'ape','\u224B':'apid','\u224B\u0338':'napid','\u224C':'bcong','\u224D':'CupCap','\u226D':'NotCupCap','\u224D\u20D2':'nvap','\u224E':'bump','\u224E\u0338':'nbump','\u224F':'bumpe','\u224F\u0338':'nbumpe','\u2250':'doteq','\u2250\u0338':'nedot','\u2251':'eDot','\u2252':'efDot','\u2253':'erDot','\u2254':'colone','\u2255':'ecolon','\u2256':'ecir','\u2257':'cire','\u2259':'wedgeq','\u225A':'veeeq','\u225C':'trie','\u225F':'equest','\u2261':'equiv','\u2262':'nequiv','\u2261\u20E5':'bnequiv','\u2264':'le','\u2270':'nle','\u2264\u20D2':'nvle','\u2265':'ge','\u2271':'nge','\u2265\u20D2':'nvge','\u2266':'lE','\u2266\u0338':'nlE','\u2267':'gE','\u2267\u0338':'ngE','\u2268\uFE00':'lvnE','\u2268':'lnE','\u2269':'gnE','\u2269\uFE00':'gvnE','\u226A':'ll','\u226A\u0338':'nLtv','\u226A\u20D2':'nLt','\u226B':'gg','\u226B\u0338':'nGtv','\u226B\u20D2':'nGt','\u226C':'twixt','\u2272':'lsim','\u2274':'nlsim','\u2273':'gsim','\u2275':'ngsim','\u2276':'lg','\u2278':'ntlg','\u2277':'gl','\u2279':'ntgl','\u227A':'pr','\u2280':'npr','\u227B':'sc','\u2281':'nsc','\u227C':'prcue','\u22E0':'nprcue','\u227D':'sccue','\u22E1':'nsccue','\u227E':'prsim','\u227F':'scsim','\u227F\u0338':'NotSucceedsTilde','\u2282':'sub','\u2284':'nsub','\u2282\u20D2':'vnsub','\u2283':'sup','\u2285':'nsup','\u2283\u20D2':'vnsup','\u2286':'sube','\u2288':'nsube','\u2287':'supe','\u2289':'nsupe','\u228A\uFE00':'vsubne','\u228A':'subne','\u228B\uFE00':'vsupne','\u228B':'supne','\u228D':'cupdot','\u228E':'uplus','\u228F':'sqsub','\u228F\u0338':'NotSquareSubset','\u2290':'sqsup','\u2290\u0338':'NotSquareSuperset','\u2291':'sqsube','\u22E2':'nsqsube','\u2292':'sqsupe','\u22E3':'nsqsupe','\u2293':'sqcap','\u2293\uFE00':'sqcaps','\u2294':'sqcup','\u2294\uFE00':'sqcups','\u2295':'oplus','\u2296':'ominus','\u2297':'otimes','\u2298':'osol','\u2299':'odot','\u229A':'ocir','\u229B':'oast','\u229D':'odash','\u229E':'plusb','\u229F':'minusb','\u22A0':'timesb','\u22A1':'sdotb','\u22A2':'vdash','\u22AC':'nvdash','\u22A3':'dashv','\u22A4':'top','\u22A5':'bot','\u22A7':'models','\u22A8':'vDash','\u22AD':'nvDash','\u22A9':'Vdash','\u22AE':'nVdash','\u22AA':'Vvdash','\u22AB':'VDash','\u22AF':'nVDash','\u22B0':'prurel','\u22B2':'vltri','\u22EA':'nltri','\u22B3':'vrtri','\u22EB':'nrtri','\u22B4':'ltrie','\u22EC':'nltrie','\u22B4\u20D2':'nvltrie','\u22B5':'rtrie','\u22ED':'nrtrie','\u22B5\u20D2':'nvrtrie','\u22B6':'origof','\u22B7':'imof','\u22B8':'mumap','\u22B9':'hercon','\u22BA':'intcal','\u22BB':'veebar','\u22BD':'barvee','\u22BE':'angrtvb','\u22BF':'lrtri','\u22C0':'Wedge','\u22C1':'Vee','\u22C2':'xcap','\u22C3':'xcup','\u22C4':'diam','\u22C5':'sdot','\u22C6':'Star','\u22C7':'divonx','\u22C8':'bowtie','\u22C9':'ltimes','\u22CA':'rtimes','\u22CB':'lthree','\u22CC':'rthree','\u22CD':'bsime','\u22CE':'cuvee','\u22CF':'cuwed','\u22D0':'Sub','\u22D1':'Sup','\u22D2':'Cap','\u22D3':'Cup','\u22D4':'fork','\u22D5':'epar','\u22D6':'ltdot','\u22D7':'gtdot','\u22D8':'Ll','\u22D8\u0338':'nLl','\u22D9':'Gg','\u22D9\u0338':'nGg','\u22DA\uFE00':'lesg','\u22DA':'leg','\u22DB':'gel','\u22DB\uFE00':'gesl','\u22DE':'cuepr','\u22DF':'cuesc','\u22E6':'lnsim','\u22E7':'gnsim','\u22E8':'prnsim','\u22E9':'scnsim','\u22EE':'vellip','\u22EF':'ctdot','\u22F0':'utdot','\u22F1':'dtdot','\u22F2':'disin','\u22F3':'isinsv','\u22F4':'isins','\u22F5':'isindot','\u22F5\u0338':'notindot','\u22F6':'notinvc','\u22F7':'notinvb','\u22F9':'isinE','\u22F9\u0338':'notinE','\u22FA':'nisd','\u22FB':'xnis','\u22FC':'nis','\u22FD':'notnivc','\u22FE':'notnivb','\u2305':'barwed','\u2306':'Barwed','\u230C':'drcrop','\u230D':'dlcrop','\u230E':'urcrop','\u230F':'ulcrop','\u2310':'bnot','\u2312':'profline','\u2313':'profsurf','\u2315':'telrec','\u2316':'target','\u231C':'ulcorn','\u231D':'urcorn','\u231E':'dlcorn','\u231F':'drcorn','\u2322':'frown','\u2323':'smile','\u232D':'cylcty','\u232E':'profalar','\u2336':'topbot','\u233D':'ovbar','\u233F':'solbar','\u237C':'angzarr','\u23B0':'lmoust','\u23B1':'rmoust','\u23B4':'tbrk','\u23B5':'bbrk','\u23B6':'bbrktbrk','\u23DC':'OverParenthesis','\u23DD':'UnderParenthesis','\u23DE':'OverBrace','\u23DF':'UnderBrace','\u23E2':'trpezium','\u23E7':'elinters','\u2423':'blank','\u2500':'boxh','\u2502':'boxv','\u250C':'boxdr','\u2510':'boxdl','\u2514':'boxur','\u2518':'boxul','\u251C':'boxvr','\u2524':'boxvl','\u252C':'boxhd','\u2534':'boxhu','\u253C':'boxvh','\u2550':'boxH','\u2551':'boxV','\u2552':'boxdR','\u2553':'boxDr','\u2554':'boxDR','\u2555':'boxdL','\u2556':'boxDl','\u2557':'boxDL','\u2558':'boxuR','\u2559':'boxUr','\u255A':'boxUR','\u255B':'boxuL','\u255C':'boxUl','\u255D':'boxUL','\u255E':'boxvR','\u255F':'boxVr','\u2560':'boxVR','\u2561':'boxvL','\u2562':'boxVl','\u2563':'boxVL','\u2564':'boxHd','\u2565':'boxhD','\u2566':'boxHD','\u2567':'boxHu','\u2568':'boxhU','\u2569':'boxHU','\u256A':'boxvH','\u256B':'boxVh','\u256C':'boxVH','\u2580':'uhblk','\u2584':'lhblk','\u2588':'block','\u2591':'blk14','\u2592':'blk12','\u2593':'blk34','\u25A1':'squ','\u25AA':'squf','\u25AB':'EmptyVerySmallSquare','\u25AD':'rect','\u25AE':'marker','\u25B1':'fltns','\u25B3':'xutri','\u25B4':'utrif','\u25B5':'utri','\u25B8':'rtrif','\u25B9':'rtri','\u25BD':'xdtri','\u25BE':'dtrif','\u25BF':'dtri','\u25C2':'ltrif','\u25C3':'ltri','\u25CA':'loz','\u25CB':'cir','\u25EC':'tridot','\u25EF':'xcirc','\u25F8':'ultri','\u25F9':'urtri','\u25FA':'lltri','\u25FB':'EmptySmallSquare','\u25FC':'FilledSmallSquare','\u2605':'starf','\u2606':'star','\u260E':'phone','\u2640':'female','\u2642':'male','\u2660':'spades','\u2663':'clubs','\u2665':'hearts','\u2666':'diams','\u266A':'sung','\u2713':'check','\u2717':'cross','\u2720':'malt','\u2736':'sext','\u2758':'VerticalSeparator','\u27C8':'bsolhsub','\u27C9':'suphsol','\u27F5':'xlarr','\u27F6':'xrarr','\u27F7':'xharr','\u27F8':'xlArr','\u27F9':'xrArr','\u27FA':'xhArr','\u27FC':'xmap','\u27FF':'dzigrarr','\u2902':'nvlArr','\u2903':'nvrArr','\u2904':'nvHarr','\u2905':'Map','\u290C':'lbarr','\u290D':'rbarr','\u290E':'lBarr','\u290F':'rBarr','\u2910':'RBarr','\u2911':'DDotrahd','\u2912':'UpArrowBar','\u2913':'DownArrowBar','\u2916':'Rarrtl','\u2919':'latail','\u291A':'ratail','\u291B':'lAtail','\u291C':'rAtail','\u291D':'larrfs','\u291E':'rarrfs','\u291F':'larrbfs','\u2920':'rarrbfs','\u2923':'nwarhk','\u2924':'nearhk','\u2925':'searhk','\u2926':'swarhk','\u2927':'nwnear','\u2928':'toea','\u2929':'tosa','\u292A':'swnwar','\u2933':'rarrc','\u2933\u0338':'nrarrc','\u2935':'cudarrr','\u2936':'ldca','\u2937':'rdca','\u2938':'cudarrl','\u2939':'larrpl','\u293C':'curarrm','\u293D':'cularrp','\u2945':'rarrpl','\u2948':'harrcir','\u2949':'Uarrocir','\u294A':'lurdshar','\u294B':'ldrushar','\u294E':'LeftRightVector','\u294F':'RightUpDownVector','\u2950':'DownLeftRightVector','\u2951':'LeftUpDownVector','\u2952':'LeftVectorBar','\u2953':'RightVectorBar','\u2954':'RightUpVectorBar','\u2955':'RightDownVectorBar','\u2956':'DownLeftVectorBar','\u2957':'DownRightVectorBar','\u2958':'LeftUpVectorBar','\u2959':'LeftDownVectorBar','\u295A':'LeftTeeVector','\u295B':'RightTeeVector','\u295C':'RightUpTeeVector','\u295D':'RightDownTeeVector','\u295E':'DownLeftTeeVector','\u295F':'DownRightTeeVector','\u2960':'LeftUpTeeVector','\u2961':'LeftDownTeeVector','\u2962':'lHar','\u2963':'uHar','\u2964':'rHar','\u2965':'dHar','\u2966':'luruhar','\u2967':'ldrdhar','\u2968':'ruluhar','\u2969':'rdldhar','\u296A':'lharul','\u296B':'llhard','\u296C':'rharul','\u296D':'lrhard','\u296E':'udhar','\u296F':'duhar','\u2970':'RoundImplies','\u2971':'erarr','\u2972':'simrarr','\u2973':'larrsim','\u2974':'rarrsim','\u2975':'rarrap','\u2976':'ltlarr','\u2978':'gtrarr','\u2979':'subrarr','\u297B':'suplarr','\u297C':'lfisht','\u297D':'rfisht','\u297E':'ufisht','\u297F':'dfisht','\u299A':'vzigzag','\u299C':'vangrt','\u299D':'angrtvbd','\u29A4':'ange','\u29A5':'range','\u29A6':'dwangle','\u29A7':'uwangle','\u29A8':'angmsdaa','\u29A9':'angmsdab','\u29AA':'angmsdac','\u29AB':'angmsdad','\u29AC':'angmsdae','\u29AD':'angmsdaf','\u29AE':'angmsdag','\u29AF':'angmsdah','\u29B0':'bemptyv','\u29B1':'demptyv','\u29B2':'cemptyv','\u29B3':'raemptyv','\u29B4':'laemptyv','\u29B5':'ohbar','\u29B6':'omid','\u29B7':'opar','\u29B9':'operp','\u29BB':'olcross','\u29BC':'odsold','\u29BE':'olcir','\u29BF':'ofcir','\u29C0':'olt','\u29C1':'ogt','\u29C2':'cirscir','\u29C3':'cirE','\u29C4':'solb','\u29C5':'bsolb','\u29C9':'boxbox','\u29CD':'trisb','\u29CE':'rtriltri','\u29CF':'LeftTriangleBar','\u29CF\u0338':'NotLeftTriangleBar','\u29D0':'RightTriangleBar','\u29D0\u0338':'NotRightTriangleBar','\u29DC':'iinfin','\u29DD':'infintie','\u29DE':'nvinfin','\u29E3':'eparsl','\u29E4':'smeparsl','\u29E5':'eqvparsl','\u29EB':'lozf','\u29F4':'RuleDelayed','\u29F6':'dsol','\u2A00':'xodot','\u2A01':'xoplus','\u2A02':'xotime','\u2A04':'xuplus','\u2A06':'xsqcup','\u2A0D':'fpartint','\u2A10':'cirfnint','\u2A11':'awint','\u2A12':'rppolint','\u2A13':'scpolint','\u2A14':'npolint','\u2A15':'pointint','\u2A16':'quatint','\u2A17':'intlarhk','\u2A22':'pluscir','\u2A23':'plusacir','\u2A24':'simplus','\u2A25':'plusdu','\u2A26':'plussim','\u2A27':'plustwo','\u2A29':'mcomma','\u2A2A':'minusdu','\u2A2D':'loplus','\u2A2E':'roplus','\u2A2F':'Cross','\u2A30':'timesd','\u2A31':'timesbar','\u2A33':'smashp','\u2A34':'lotimes','\u2A35':'rotimes','\u2A36':'otimesas','\u2A37':'Otimes','\u2A38':'odiv','\u2A39':'triplus','\u2A3A':'triminus','\u2A3B':'tritime','\u2A3C':'iprod','\u2A3F':'amalg','\u2A40':'capdot','\u2A42':'ncup','\u2A43':'ncap','\u2A44':'capand','\u2A45':'cupor','\u2A46':'cupcap','\u2A47':'capcup','\u2A48':'cupbrcap','\u2A49':'capbrcup','\u2A4A':'cupcup','\u2A4B':'capcap','\u2A4C':'ccups','\u2A4D':'ccaps','\u2A50':'ccupssm','\u2A53':'And','\u2A54':'Or','\u2A55':'andand','\u2A56':'oror','\u2A57':'orslope','\u2A58':'andslope','\u2A5A':'andv','\u2A5B':'orv','\u2A5C':'andd','\u2A5D':'ord','\u2A5F':'wedbar','\u2A66':'sdote','\u2A6A':'simdot','\u2A6D':'congdot','\u2A6D\u0338':'ncongdot','\u2A6E':'easter','\u2A6F':'apacir','\u2A70':'apE','\u2A70\u0338':'napE','\u2A71':'eplus','\u2A72':'pluse','\u2A73':'Esim','\u2A77':'eDDot','\u2A78':'equivDD','\u2A79':'ltcir','\u2A7A':'gtcir','\u2A7B':'ltquest','\u2A7C':'gtquest','\u2A7D':'les','\u2A7D\u0338':'nles','\u2A7E':'ges','\u2A7E\u0338':'nges','\u2A7F':'lesdot','\u2A80':'gesdot','\u2A81':'lesdoto','\u2A82':'gesdoto','\u2A83':'lesdotor','\u2A84':'gesdotol','\u2A85':'lap','\u2A86':'gap','\u2A87':'lne','\u2A88':'gne','\u2A89':'lnap','\u2A8A':'gnap','\u2A8B':'lEg','\u2A8C':'gEl','\u2A8D':'lsime','\u2A8E':'gsime','\u2A8F':'lsimg','\u2A90':'gsiml','\u2A91':'lgE','\u2A92':'glE','\u2A93':'lesges','\u2A94':'gesles','\u2A95':'els','\u2A96':'egs','\u2A97':'elsdot','\u2A98':'egsdot','\u2A99':'el','\u2A9A':'eg','\u2A9D':'siml','\u2A9E':'simg','\u2A9F':'simlE','\u2AA0':'simgE','\u2AA1':'LessLess','\u2AA1\u0338':'NotNestedLessLess','\u2AA2':'GreaterGreater','\u2AA2\u0338':'NotNestedGreaterGreater','\u2AA4':'glj','\u2AA5':'gla','\u2AA6':'ltcc','\u2AA7':'gtcc','\u2AA8':'lescc','\u2AA9':'gescc','\u2AAA':'smt','\u2AAB':'lat','\u2AAC':'smte','\u2AAC\uFE00':'smtes','\u2AAD':'late','\u2AAD\uFE00':'lates','\u2AAE':'bumpE','\u2AAF':'pre','\u2AAF\u0338':'npre','\u2AB0':'sce','\u2AB0\u0338':'nsce','\u2AB3':'prE','\u2AB4':'scE','\u2AB5':'prnE','\u2AB6':'scnE','\u2AB7':'prap','\u2AB8':'scap','\u2AB9':'prnap','\u2ABA':'scnap','\u2ABB':'Pr','\u2ABC':'Sc','\u2ABD':'subdot','\u2ABE':'supdot','\u2ABF':'subplus','\u2AC0':'supplus','\u2AC1':'submult','\u2AC2':'supmult','\u2AC3':'subedot','\u2AC4':'supedot','\u2AC5':'subE','\u2AC5\u0338':'nsubE','\u2AC6':'supE','\u2AC6\u0338':'nsupE','\u2AC7':'subsim','\u2AC8':'supsim','\u2ACB\uFE00':'vsubnE','\u2ACB':'subnE','\u2ACC\uFE00':'vsupnE','\u2ACC':'supnE','\u2ACF':'csub','\u2AD0':'csup','\u2AD1':'csube','\u2AD2':'csupe','\u2AD3':'subsup','\u2AD4':'supsub','\u2AD5':'subsub','\u2AD6':'supsup','\u2AD7':'suphsub','\u2AD8':'supdsub','\u2AD9':'forkv','\u2ADA':'topfork','\u2ADB':'mlcp','\u2AE4':'Dashv','\u2AE6':'Vdashl','\u2AE7':'Barv','\u2AE8':'vBar','\u2AE9':'vBarv','\u2AEB':'Vbar','\u2AEC':'Not','\u2AED':'bNot','\u2AEE':'rnmid','\u2AEF':'cirmid','\u2AF0':'midcir','\u2AF1':'topcir','\u2AF2':'nhpar','\u2AF3':'parsim','\u2AFD':'parsl','\u2AFD\u20E5':'nparsl','\u266D':'flat','\u266E':'natur','\u266F':'sharp','\xA4':'curren','\xA2':'cent','$':'dollar','\xA3':'pound','\xA5':'yen','\u20AC':'euro','\xB9':'sup1','\xBD':'half','\u2153':'frac13','\xBC':'frac14','\u2155':'frac15','\u2159':'frac16','\u215B':'frac18','\xB2':'sup2','\u2154':'frac23','\u2156':'frac25','\xB3':'sup3','\xBE':'frac34','\u2157':'frac35','\u215C':'frac38','\u2158':'frac45','\u215A':'frac56','\u215D':'frac58','\u215E':'frac78','\uD835\uDCB6':'ascr','\uD835\uDD52':'aopf','\uD835\uDD1E':'afr','\uD835\uDD38':'Aopf','\uD835\uDD04':'Afr','\uD835\uDC9C':'Ascr','\xAA':'ordf','\xE1':'aacute','\xC1':'Aacute','\xE0':'agrave','\xC0':'Agrave','\u0103':'abreve','\u0102':'Abreve','\xE2':'acirc','\xC2':'Acirc','\xE5':'aring','\xC5':'angst','\xE4':'auml','\xC4':'Auml','\xE3':'atilde','\xC3':'Atilde','\u0105':'aogon','\u0104':'Aogon','\u0101':'amacr','\u0100':'Amacr','\xE6':'aelig','\xC6':'AElig','\uD835\uDCB7':'bscr','\uD835\uDD53':'bopf','\uD835\uDD1F':'bfr','\uD835\uDD39':'Bopf','\u212C':'Bscr','\uD835\uDD05':'Bfr','\uD835\uDD20':'cfr','\uD835\uDCB8':'cscr','\uD835\uDD54':'copf','\u212D':'Cfr','\uD835\uDC9E':'Cscr','\u2102':'Copf','\u0107':'cacute','\u0106':'Cacute','\u0109':'ccirc','\u0108':'Ccirc','\u010D':'ccaron','\u010C':'Ccaron','\u010B':'cdot','\u010A':'Cdot','\xE7':'ccedil','\xC7':'Ccedil','\u2105':'incare','\uD835\uDD21':'dfr','\u2146':'dd','\uD835\uDD55':'dopf','\uD835\uDCB9':'dscr','\uD835\uDC9F':'Dscr','\uD835\uDD07':'Dfr','\u2145':'DD','\uD835\uDD3B':'Dopf','\u010F':'dcaron','\u010E':'Dcaron','\u0111':'dstrok','\u0110':'Dstrok','\xF0':'eth','\xD0':'ETH','\u2147':'ee','\u212F':'escr','\uD835\uDD22':'efr','\uD835\uDD56':'eopf','\u2130':'Escr','\uD835\uDD08':'Efr','\uD835\uDD3C':'Eopf','\xE9':'eacute','\xC9':'Eacute','\xE8':'egrave','\xC8':'Egrave','\xEA':'ecirc','\xCA':'Ecirc','\u011B':'ecaron','\u011A':'Ecaron','\xEB':'euml','\xCB':'Euml','\u0117':'edot','\u0116':'Edot','\u0119':'eogon','\u0118':'Eogon','\u0113':'emacr','\u0112':'Emacr','\uD835\uDD23':'ffr','\uD835\uDD57':'fopf','\uD835\uDCBB':'fscr','\uD835\uDD09':'Ffr','\uD835\uDD3D':'Fopf','\u2131':'Fscr','\uFB00':'fflig','\uFB03':'ffilig','\uFB04':'ffllig','\uFB01':'filig','fj':'fjlig','\uFB02':'fllig','\u0192':'fnof','\u210A':'gscr','\uD835\uDD58':'gopf','\uD835\uDD24':'gfr','\uD835\uDCA2':'Gscr','\uD835\uDD3E':'Gopf','\uD835\uDD0A':'Gfr','\u01F5':'gacute','\u011F':'gbreve','\u011E':'Gbreve','\u011D':'gcirc','\u011C':'Gcirc','\u0121':'gdot','\u0120':'Gdot','\u0122':'Gcedil','\uD835\uDD25':'hfr','\u210E':'planckh','\uD835\uDCBD':'hscr','\uD835\uDD59':'hopf','\u210B':'Hscr','\u210C':'Hfr','\u210D':'Hopf','\u0125':'hcirc','\u0124':'Hcirc','\u210F':'hbar','\u0127':'hstrok','\u0126':'Hstrok','\uD835\uDD5A':'iopf','\uD835\uDD26':'ifr','\uD835\uDCBE':'iscr','\u2148':'ii','\uD835\uDD40':'Iopf','\u2110':'Iscr','\u2111':'Im','\xED':'iacute','\xCD':'Iacute','\xEC':'igrave','\xCC':'Igrave','\xEE':'icirc','\xCE':'Icirc','\xEF':'iuml','\xCF':'Iuml','\u0129':'itilde','\u0128':'Itilde','\u0130':'Idot','\u012F':'iogon','\u012E':'Iogon','\u012B':'imacr','\u012A':'Imacr','\u0133':'ijlig','\u0132':'IJlig','\u0131':'imath','\uD835\uDCBF':'jscr','\uD835\uDD5B':'jopf','\uD835\uDD27':'jfr','\uD835\uDCA5':'Jscr','\uD835\uDD0D':'Jfr','\uD835\uDD41':'Jopf','\u0135':'jcirc','\u0134':'Jcirc','\u0237':'jmath','\uD835\uDD5C':'kopf','\uD835\uDCC0':'kscr','\uD835\uDD28':'kfr','\uD835\uDCA6':'Kscr','\uD835\uDD42':'Kopf','\uD835\uDD0E':'Kfr','\u0137':'kcedil','\u0136':'Kcedil','\uD835\uDD29':'lfr','\uD835\uDCC1':'lscr','\u2113':'ell','\uD835\uDD5D':'lopf','\u2112':'Lscr','\uD835\uDD0F':'Lfr','\uD835\uDD43':'Lopf','\u013A':'lacute','\u0139':'Lacute','\u013E':'lcaron','\u013D':'Lcaron','\u013C':'lcedil','\u013B':'Lcedil','\u0142':'lstrok','\u0141':'Lstrok','\u0140':'lmidot','\u013F':'Lmidot','\uD835\uDD2A':'mfr','\uD835\uDD5E':'mopf','\uD835\uDCC2':'mscr','\uD835\uDD10':'Mfr','\uD835\uDD44':'Mopf','\u2133':'Mscr','\uD835\uDD2B':'nfr','\uD835\uDD5F':'nopf','\uD835\uDCC3':'nscr','\u2115':'Nopf','\uD835\uDCA9':'Nscr','\uD835\uDD11':'Nfr','\u0144':'nacute','\u0143':'Nacute','\u0148':'ncaron','\u0147':'Ncaron','\xF1':'ntilde','\xD1':'Ntilde','\u0146':'ncedil','\u0145':'Ncedil','\u2116':'numero','\u014B':'eng','\u014A':'ENG','\uD835\uDD60':'oopf','\uD835\uDD2C':'ofr','\u2134':'oscr','\uD835\uDCAA':'Oscr','\uD835\uDD12':'Ofr','\uD835\uDD46':'Oopf','\xBA':'ordm','\xF3':'oacute','\xD3':'Oacute','\xF2':'ograve','\xD2':'Ograve','\xF4':'ocirc','\xD4':'Ocirc','\xF6':'ouml','\xD6':'Ouml','\u0151':'odblac','\u0150':'Odblac','\xF5':'otilde','\xD5':'Otilde','\xF8':'oslash','\xD8':'Oslash','\u014D':'omacr','\u014C':'Omacr','\u0153':'oelig','\u0152':'OElig','\uD835\uDD2D':'pfr','\uD835\uDCC5':'pscr','\uD835\uDD61':'popf','\u2119':'Popf','\uD835\uDD13':'Pfr','\uD835\uDCAB':'Pscr','\uD835\uDD62':'qopf','\uD835\uDD2E':'qfr','\uD835\uDCC6':'qscr','\uD835\uDCAC':'Qscr','\uD835\uDD14':'Qfr','\u211A':'Qopf','\u0138':'kgreen','\uD835\uDD2F':'rfr','\uD835\uDD63':'ropf','\uD835\uDCC7':'rscr','\u211B':'Rscr','\u211C':'Re','\u211D':'Ropf','\u0155':'racute','\u0154':'Racute','\u0159':'rcaron','\u0158':'Rcaron','\u0157':'rcedil','\u0156':'Rcedil','\uD835\uDD64':'sopf','\uD835\uDCC8':'sscr','\uD835\uDD30':'sfr','\uD835\uDD4A':'Sopf','\uD835\uDD16':'Sfr','\uD835\uDCAE':'Sscr','\u24C8':'oS','\u015B':'sacute','\u015A':'Sacute','\u015D':'scirc','\u015C':'Scirc','\u0161':'scaron','\u0160':'Scaron','\u015F':'scedil','\u015E':'Scedil','\xDF':'szlig','\uD835\uDD31':'tfr','\uD835\uDCC9':'tscr','\uD835\uDD65':'topf','\uD835\uDCAF':'Tscr','\uD835\uDD17':'Tfr','\uD835\uDD4B':'Topf','\u0165':'tcaron','\u0164':'Tcaron','\u0163':'tcedil','\u0162':'Tcedil','\u2122':'trade','\u0167':'tstrok','\u0166':'Tstrok','\uD835\uDCCA':'uscr','\uD835\uDD66':'uopf','\uD835\uDD32':'ufr','\uD835\uDD4C':'Uopf','\uD835\uDD18':'Ufr','\uD835\uDCB0':'Uscr','\xFA':'uacute','\xDA':'Uacute','\xF9':'ugrave','\xD9':'Ugrave','\u016D':'ubreve','\u016C':'Ubreve','\xFB':'ucirc','\xDB':'Ucirc','\u016F':'uring','\u016E':'Uring','\xFC':'uuml','\xDC':'Uuml','\u0171':'udblac','\u0170':'Udblac','\u0169':'utilde','\u0168':'Utilde','\u0173':'uogon','\u0172':'Uogon','\u016B':'umacr','\u016A':'Umacr','\uD835\uDD33':'vfr','\uD835\uDD67':'vopf','\uD835\uDCCB':'vscr','\uD835\uDD19':'Vfr','\uD835\uDD4D':'Vopf','\uD835\uDCB1':'Vscr','\uD835\uDD68':'wopf','\uD835\uDCCC':'wscr','\uD835\uDD34':'wfr','\uD835\uDCB2':'Wscr','\uD835\uDD4E':'Wopf','\uD835\uDD1A':'Wfr','\u0175':'wcirc','\u0174':'Wcirc','\uD835\uDD35':'xfr','\uD835\uDCCD':'xscr','\uD835\uDD69':'xopf','\uD835\uDD4F':'Xopf','\uD835\uDD1B':'Xfr','\uD835\uDCB3':'Xscr','\uD835\uDD36':'yfr','\uD835\uDCCE':'yscr','\uD835\uDD6A':'yopf','\uD835\uDCB4':'Yscr','\uD835\uDD1C':'Yfr','\uD835\uDD50':'Yopf','\xFD':'yacute','\xDD':'Yacute','\u0177':'ycirc','\u0176':'Ycirc','\xFF':'yuml','\u0178':'Yuml','\uD835\uDCCF':'zscr','\uD835\uDD37':'zfr','\uD835\uDD6B':'zopf','\u2128':'Zfr','\u2124':'Zopf','\uD835\uDCB5':'Zscr','\u017A':'zacute','\u0179':'Zacute','\u017E':'zcaron','\u017D':'Zcaron','\u017C':'zdot','\u017B':'Zdot','\u01B5':'imped','\xFE':'thorn','\xDE':'THORN','\u0149':'napos','\u03B1':'alpha','\u0391':'Alpha','\u03B2':'beta','\u0392':'Beta','\u03B3':'gamma','\u0393':'Gamma','\u03B4':'delta','\u0394':'Delta','\u03B5':'epsi','\u03F5':'epsiv','\u0395':'Epsilon','\u03DD':'gammad','\u03DC':'Gammad','\u03B6':'zeta','\u0396':'Zeta','\u03B7':'eta','\u0397':'Eta','\u03B8':'theta','\u03D1':'thetav','\u0398':'Theta','\u03B9':'iota','\u0399':'Iota','\u03BA':'kappa','\u03F0':'kappav','\u039A':'Kappa','\u03BB':'lambda','\u039B':'Lambda','\u03BC':'mu','\xB5':'micro','\u039C':'Mu','\u03BD':'nu','\u039D':'Nu','\u03BE':'xi','\u039E':'Xi','\u03BF':'omicron','\u039F':'Omicron','\u03C0':'pi','\u03D6':'piv','\u03A0':'Pi','\u03C1':'rho','\u03F1':'rhov','\u03A1':'Rho','\u03C3':'sigma','\u03A3':'Sigma','\u03C2':'sigmaf','\u03C4':'tau','\u03A4':'Tau','\u03C5':'upsi','\u03A5':'Upsilon','\u03D2':'Upsi','\u03C6':'phi','\u03D5':'phiv','\u03A6':'Phi','\u03C7':'chi','\u03A7':'Chi','\u03C8':'psi','\u03A8':'Psi','\u03C9':'omega','\u03A9':'ohm','\u0430':'acy','\u0410':'Acy','\u0431':'bcy','\u0411':'Bcy','\u0432':'vcy','\u0412':'Vcy','\u0433':'gcy','\u0413':'Gcy','\u0453':'gjcy','\u0403':'GJcy','\u0434':'dcy','\u0414':'Dcy','\u0452':'djcy','\u0402':'DJcy','\u0435':'iecy','\u0415':'IEcy','\u0451':'iocy','\u0401':'IOcy','\u0454':'jukcy','\u0404':'Jukcy','\u0436':'zhcy','\u0416':'ZHcy','\u0437':'zcy','\u0417':'Zcy','\u0455':'dscy','\u0405':'DScy','\u0438':'icy','\u0418':'Icy','\u0456':'iukcy','\u0406':'Iukcy','\u0457':'yicy','\u0407':'YIcy','\u0439':'jcy','\u0419':'Jcy','\u0458':'jsercy','\u0408':'Jsercy','\u043A':'kcy','\u041A':'Kcy','\u045C':'kjcy','\u040C':'KJcy','\u043B':'lcy','\u041B':'Lcy','\u0459':'ljcy','\u0409':'LJcy','\u043C':'mcy','\u041C':'Mcy','\u043D':'ncy','\u041D':'Ncy','\u045A':'njcy','\u040A':'NJcy','\u043E':'ocy','\u041E':'Ocy','\u043F':'pcy','\u041F':'Pcy','\u0440':'rcy','\u0420':'Rcy','\u0441':'scy','\u0421':'Scy','\u0442':'tcy','\u0422':'Tcy','\u045B':'tshcy','\u040B':'TSHcy','\u0443':'ucy','\u0423':'Ucy','\u045E':'ubrcy','\u040E':'Ubrcy','\u0444':'fcy','\u0424':'Fcy','\u0445':'khcy','\u0425':'KHcy','\u0446':'tscy','\u0426':'TScy','\u0447':'chcy','\u0427':'CHcy','\u045F':'dzcy','\u040F':'DZcy','\u0448':'shcy','\u0428':'SHcy','\u0449':'shchcy','\u0429':'SHCHcy','\u044A':'hardcy','\u042A':'HARDcy','\u044B':'ycy','\u042B':'Ycy','\u044C':'softcy','\u042C':'SOFTcy','\u044D':'ecy','\u042D':'Ecy','\u044E':'yucy','\u042E':'YUcy','\u044F':'yacy','\u042F':'YAcy','\u2135':'aleph','\u2136':'beth','\u2137':'gimel','\u2138':'daleth'};
+
+ var regexEscape = /["&'<>`]/g;
+ var escapeMap = {
+ '"': '"',
+ '&': '&',
+ '\'': ''',
+ '<': '<',
+ // See https://mathiasbynens.be/notes/ambiguous-ampersands: in HTML, the
+ // following is not strictly necessary unless it’s part of a tag or an
+ // unquoted attribute value. We’re only escaping it to support those
+ // situations, and for XML support.
+ '>': '>',
+ // In Internet Explorer ≤ 8, the backtick character can be used
+ // to break out of (un)quoted attribute values or HTML comments.
+ // See http://html5sec.org/#102, http://html5sec.org/#108, and
+ // http://html5sec.org/#133.
+ '`': '`'
+ };
+
+ var regexInvalidEntity = /(?:[xX][^a-fA-F0-9]|[^0-9xX])/;
+ var regexInvalidRawCodePoint = /[\0-\x08\x0B\x0E-\x1F\x7F-\x9F\uFDD0-\uFDEF\uFFFE\uFFFF]|[\uD83F\uD87F\uD8BF\uD8FF\uD93F\uD97F\uD9BF\uD9FF\uDA3F\uDA7F\uDABF\uDAFF\uDB3F\uDB7F\uDBBF\uDBFF][\uDFFE\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
+ var regexDecode = /&(CounterClockwiseContourIntegral|DoubleLongLeftRightArrow|ClockwiseContourIntegral|NotNestedGreaterGreater|NotSquareSupersetEqual|DiacriticalDoubleAcute|NotRightTriangleEqual|NotSucceedsSlantEqual|NotPrecedesSlantEqual|CloseCurlyDoubleQuote|NegativeVeryThinSpace|DoubleContourIntegral|FilledVerySmallSquare|CapitalDifferentialD|OpenCurlyDoubleQuote|EmptyVerySmallSquare|NestedGreaterGreater|DoubleLongRightArrow|NotLeftTriangleEqual|NotGreaterSlantEqual|ReverseUpEquilibrium|DoubleLeftRightArrow|NotSquareSubsetEqual|NotDoubleVerticalBar|RightArrowLeftArrow|NotGreaterFullEqual|NotRightTriangleBar|SquareSupersetEqual|DownLeftRightVector|DoubleLongLeftArrow|leftrightsquigarrow|LeftArrowRightArrow|NegativeMediumSpace|blacktriangleright|RightDownVectorBar|PrecedesSlantEqual|RightDoubleBracket|SucceedsSlantEqual|NotLeftTriangleBar|RightTriangleEqual|SquareIntersection|RightDownTeeVector|ReverseEquilibrium|NegativeThickSpace|longleftrightarrow|Longleftrightarrow|LongLeftRightArrow|DownRightTeeVector|DownRightVectorBar|GreaterSlantEqual|SquareSubsetEqual|LeftDownVectorBar|LeftDoubleBracket|VerticalSeparator|rightleftharpoons|NotGreaterGreater|NotSquareSuperset|blacktriangleleft|blacktriangledown|NegativeThinSpace|LeftDownTeeVector|NotLessSlantEqual|leftrightharpoons|DoubleUpDownArrow|DoubleVerticalBar|LeftTriangleEqual|FilledSmallSquare|twoheadrightarrow|NotNestedLessLess|DownLeftTeeVector|DownLeftVectorBar|RightAngleBracket|NotTildeFullEqual|NotReverseElement|RightUpDownVector|DiacriticalTilde|NotSucceedsTilde|circlearrowright|NotPrecedesEqual|rightharpoondown|DoubleRightArrow|NotSucceedsEqual|NonBreakingSpace|NotRightTriangle|LessEqualGreater|RightUpTeeVector|LeftAngleBracket|GreaterFullEqual|DownArrowUpArrow|RightUpVectorBar|twoheadleftarrow|GreaterEqualLess|downharpoonright|RightTriangleBar|ntrianglerighteq|NotSupersetEqual|LeftUpDownVector|DiacriticalAcute|rightrightarrows|vartriangleright|UpArrowDownArrow|DiacriticalGrave|UnderParenthesis|EmptySmallSquare|LeftUpVectorBar|leftrightarrows|DownRightVector|downharpoonleft|trianglerighteq|ShortRightArrow|OverParenthesis|DoubleLeftArrow|DoubleDownArrow|NotSquareSubset|bigtriangledown|ntrianglelefteq|UpperRightArrow|curvearrowright|vartriangleleft|NotLeftTriangle|nleftrightarrow|LowerRightArrow|NotHumpDownHump|NotGreaterTilde|rightthreetimes|LeftUpTeeVector|NotGreaterEqual|straightepsilon|LeftTriangleBar|rightsquigarrow|ContourIntegral|rightleftarrows|CloseCurlyQuote|RightDownVector|LeftRightVector|nLeftrightarrow|leftharpoondown|circlearrowleft|SquareSuperset|OpenCurlyQuote|hookrightarrow|HorizontalLine|DiacriticalDot|NotLessGreater|ntriangleright|DoubleRightTee|InvisibleComma|InvisibleTimes|LowerLeftArrow|DownLeftVector|NotSubsetEqual|curvearrowleft|trianglelefteq|NotVerticalBar|TildeFullEqual|downdownarrows|NotGreaterLess|RightTeeVector|ZeroWidthSpace|looparrowright|LongRightArrow|doublebarwedge|ShortLeftArrow|ShortDownArrow|RightVectorBar|GreaterGreater|ReverseElement|rightharpoonup|LessSlantEqual|leftthreetimes|upharpoonright|rightarrowtail|LeftDownVector|Longrightarrow|NestedLessLess|UpperLeftArrow|nshortparallel|leftleftarrows|leftrightarrow|Leftrightarrow|LeftRightArrow|longrightarrow|upharpoonleft|RightArrowBar|ApplyFunction|LeftTeeVector|leftarrowtail|NotEqualTilde|varsubsetneqq|varsupsetneqq|RightTeeArrow|SucceedsEqual|SucceedsTilde|LeftVectorBar|SupersetEqual|hookleftarrow|DifferentialD|VerticalTilde|VeryThinSpace|blacktriangle|bigtriangleup|LessFullEqual|divideontimes|leftharpoonup|UpEquilibrium|ntriangleleft|RightTriangle|measuredangle|shortparallel|longleftarrow|Longleftarrow|LongLeftArrow|DoubleLeftTee|Poincareplane|PrecedesEqual|triangleright|DoubleUpArrow|RightUpVector|fallingdotseq|looparrowleft|PrecedesTilde|NotTildeEqual|NotTildeTilde|smallsetminus|Proportional|triangleleft|triangledown|UnderBracket|NotHumpEqual|exponentiale|ExponentialE|NotLessTilde|HilbertSpace|RightCeiling|blacklozenge|varsupsetneq|HumpDownHump|GreaterEqual|VerticalLine|LeftTeeArrow|NotLessEqual|DownTeeArrow|LeftTriangle|varsubsetneq|Intersection|NotCongruent|DownArrowBar|LeftUpVector|LeftArrowBar|risingdotseq|GreaterTilde|RoundImplies|SquareSubset|ShortUpArrow|NotSuperset|quaternions|precnapprox|backepsilon|preccurlyeq|OverBracket|blacksquare|MediumSpace|VerticalBar|circledcirc|circleddash|CircleMinus|CircleTimes|LessGreater|curlyeqprec|curlyeqsucc|diamondsuit|UpDownArrow|Updownarrow|RuleDelayed|Rrightarrow|updownarrow|RightVector|nRightarrow|nrightarrow|eqslantless|LeftCeiling|Equilibrium|SmallCircle|expectation|NotSucceeds|thickapprox|GreaterLess|SquareUnion|NotPrecedes|NotLessLess|straightphi|succnapprox|succcurlyeq|SubsetEqual|sqsupseteq|Proportion|Laplacetrf|ImaginaryI|supsetneqq|NotGreater|gtreqqless|NotElement|ThickSpace|TildeEqual|TildeTilde|Fouriertrf|rmoustache|EqualTilde|eqslantgtr|UnderBrace|LeftVector|UpArrowBar|nLeftarrow|nsubseteqq|subsetneqq|nsupseteqq|nleftarrow|succapprox|lessapprox|UpTeeArrow|upuparrows|curlywedge|lesseqqgtr|varepsilon|varnothing|RightFloor|complement|CirclePlus|sqsubseteq|Lleftarrow|circledast|RightArrow|Rightarrow|rightarrow|lmoustache|Bernoullis|precapprox|mapstoleft|mapstodown|longmapsto|dotsquare|downarrow|DoubleDot|nsubseteq|supsetneq|leftarrow|nsupseteq|subsetneq|ThinSpace|ngeqslant|subseteqq|HumpEqual|NotSubset|triangleq|NotCupCap|lesseqgtr|heartsuit|TripleDot|Leftarrow|Coproduct|Congruent|varpropto|complexes|gvertneqq|LeftArrow|LessTilde|supseteqq|MinusPlus|CircleDot|nleqslant|NotExists|gtreqless|nparallel|UnionPlus|LeftFloor|checkmark|CenterDot|centerdot|Mellintrf|gtrapprox|bigotimes|OverBrace|spadesuit|therefore|pitchfork|rationals|PlusMinus|Backslash|Therefore|DownBreve|backsimeq|backprime|DownArrow|nshortmid|Downarrow|lvertneqq|eqvparsl|imagline|imagpart|infintie|integers|Integral|intercal|LessLess|Uarrocir|intlarhk|sqsupset|angmsdaf|sqsubset|llcorner|vartheta|cupbrcap|lnapprox|Superset|SuchThat|succnsim|succneqq|angmsdag|biguplus|curlyvee|trpezium|Succeeds|NotTilde|bigwedge|angmsdah|angrtvbd|triminus|cwconint|fpartint|lrcorner|smeparsl|subseteq|urcorner|lurdshar|laemptyv|DDotrahd|approxeq|ldrushar|awconint|mapstoup|backcong|shortmid|triangle|geqslant|gesdotol|timesbar|circledR|circledS|setminus|multimap|naturals|scpolint|ncongdot|RightTee|boxminus|gnapprox|boxtimes|andslope|thicksim|angmsdaa|varsigma|cirfnint|rtriltri|angmsdab|rppolint|angmsdac|barwedge|drbkarow|clubsuit|thetasym|bsolhsub|capbrcup|dzigrarr|doteqdot|DotEqual|dotminus|UnderBar|NotEqual|realpart|otimesas|ulcorner|hksearow|hkswarow|parallel|PartialD|elinters|emptyset|plusacir|bbrktbrk|angmsdad|pointint|bigoplus|angmsdae|Precedes|bigsqcup|varkappa|notindot|supseteq|precneqq|precnsim|profalar|profline|profsurf|leqslant|lesdotor|raemptyv|subplus|notnivb|notnivc|subrarr|zigrarr|vzigzag|submult|subedot|Element|between|cirscir|larrbfs|larrsim|lotimes|lbrksld|lbrkslu|lozenge|ldrdhar|dbkarow|bigcirc|epsilon|simrarr|simplus|ltquest|Epsilon|luruhar|gtquest|maltese|npolint|eqcolon|npreceq|bigodot|ddagger|gtrless|bnequiv|harrcir|ddotseq|equivDD|backsim|demptyv|nsqsube|nsqsupe|Upsilon|nsubset|upsilon|minusdu|nsucceq|swarrow|nsupset|coloneq|searrow|boxplus|napprox|natural|asympeq|alefsym|congdot|nearrow|bigstar|diamond|supplus|tritime|LeftTee|nvinfin|triplus|NewLine|nvltrie|nvrtrie|nwarrow|nexists|Diamond|ruluhar|Implies|supmult|angzarr|suplarr|suphsub|questeq|because|digamma|Because|olcross|bemptyv|omicron|Omicron|rotimes|NoBreak|intprod|angrtvb|orderof|uwangle|suphsol|lesdoto|orslope|DownTee|realine|cudarrl|rdldhar|OverBar|supedot|lessdot|supdsub|topfork|succsim|rbrkslu|rbrksld|pertenk|cudarrr|isindot|planckh|lessgtr|pluscir|gesdoto|plussim|plustwo|lesssim|cularrp|rarrsim|Cayleys|notinva|notinvb|notinvc|UpArrow|Uparrow|uparrow|NotLess|dwangle|precsim|Product|curarrm|Cconint|dotplus|rarrbfs|ccupssm|Cedilla|cemptyv|notniva|quatint|frac35|frac38|frac45|frac56|frac58|frac78|tridot|xoplus|gacute|gammad|Gammad|lfisht|lfloor|bigcup|sqsupe|gbreve|Gbreve|lharul|sqsube|sqcups|Gcedil|apacir|llhard|lmidot|Lmidot|lmoust|andand|sqcaps|approx|Abreve|spades|circeq|tprime|divide|topcir|Assign|topbot|gesdot|divonx|xuplus|timesd|gesles|atilde|solbar|SOFTcy|loplus|timesb|lowast|lowbar|dlcorn|dlcrop|softcy|dollar|lparlt|thksim|lrhard|Atilde|lsaquo|smashp|bigvee|thinsp|wreath|bkarow|lsquor|lstrok|Lstrok|lthree|ltimes|ltlarr|DotDot|simdot|ltrPar|weierp|xsqcup|angmsd|sigmav|sigmaf|zeetrf|Zcaron|zcaron|mapsto|vsupne|thetav|cirmid|marker|mcomma|Zacute|vsubnE|there4|gtlPar|vsubne|bottom|gtrarr|SHCHcy|shchcy|midast|midcir|middot|minusb|minusd|gtrdot|bowtie|sfrown|mnplus|models|colone|seswar|Colone|mstpos|searhk|gtrsim|nacute|Nacute|boxbox|telrec|hairsp|Tcedil|nbumpe|scnsim|ncaron|Ncaron|ncedil|Ncedil|hamilt|Scedil|nearhk|hardcy|HARDcy|tcedil|Tcaron|commat|nequiv|nesear|tcaron|target|hearts|nexist|varrho|scedil|Scaron|scaron|hellip|Sacute|sacute|hercon|swnwar|compfn|rtimes|rthree|rsquor|rsaquo|zacute|wedgeq|homtht|barvee|barwed|Barwed|rpargt|horbar|conint|swarhk|roplus|nltrie|hslash|hstrok|Hstrok|rmoust|Conint|bprime|hybull|hyphen|iacute|Iacute|supsup|supsub|supsim|varphi|coprod|brvbar|agrave|Supset|supset|igrave|Igrave|notinE|Agrave|iiiint|iinfin|copysr|wedbar|Verbar|vangrt|becaus|incare|verbar|inodot|bullet|drcorn|intcal|drcrop|cularr|vellip|Utilde|bumpeq|cupcap|dstrok|Dstrok|CupCap|cupcup|cupdot|eacute|Eacute|supdot|iquest|easter|ecaron|Ecaron|ecolon|isinsv|utilde|itilde|Itilde|curarr|succeq|Bumpeq|cacute|ulcrop|nparsl|Cacute|nprcue|egrave|Egrave|nrarrc|nrarrw|subsup|subsub|nrtrie|jsercy|nsccue|Jsercy|kappav|kcedil|Kcedil|subsim|ulcorn|nsimeq|egsdot|veebar|kgreen|capand|elsdot|Subset|subset|curren|aacute|lacute|Lacute|emptyv|ntilde|Ntilde|lagran|lambda|Lambda|capcap|Ugrave|langle|subdot|emsp13|numero|emsp14|nvdash|nvDash|nVdash|nVDash|ugrave|ufisht|nvHarr|larrfs|nvlArr|larrhk|larrlp|larrpl|nvrArr|Udblac|nwarhk|larrtl|nwnear|oacute|Oacute|latail|lAtail|sstarf|lbrace|odblac|Odblac|lbrack|udblac|odsold|eparsl|lcaron|Lcaron|ograve|Ograve|lcedil|Lcedil|Aacute|ssmile|ssetmn|squarf|ldquor|capcup|ominus|cylcty|rharul|eqcirc|dagger|rfloor|rfisht|Dagger|daleth|equals|origof|capdot|equest|dcaron|Dcaron|rdquor|oslash|Oslash|otilde|Otilde|otimes|Otimes|urcrop|Ubreve|ubreve|Yacute|Uacute|uacute|Rcedil|rcedil|urcorn|parsim|Rcaron|Vdashl|rcaron|Tstrok|percnt|period|permil|Exists|yacute|rbrack|rbrace|phmmat|ccaron|Ccaron|planck|ccedil|plankv|tstrok|female|plusdo|plusdu|ffilig|plusmn|ffllig|Ccedil|rAtail|dfisht|bernou|ratail|Rarrtl|rarrtl|angsph|rarrpl|rarrlp|rarrhk|xwedge|xotime|forall|ForAll|Vvdash|vsupnE|preceq|bigcap|frac12|frac13|frac14|primes|rarrfs|prnsim|frac15|Square|frac16|square|lesdot|frac18|frac23|propto|prurel|rarrap|rangle|puncsp|frac25|Racute|qprime|racute|lesges|frac34|abreve|AElig|eqsim|utdot|setmn|urtri|Equal|Uring|seArr|uring|searr|dashv|Dashv|mumap|nabla|iogon|Iogon|sdote|sdotb|scsim|napid|napos|equiv|natur|Acirc|dblac|erarr|nbump|iprod|erDot|ucirc|awint|esdot|angrt|ncong|isinE|scnap|Scirc|scirc|ndash|isins|Ubrcy|nearr|neArr|isinv|nedot|ubrcy|acute|Ycirc|iukcy|Iukcy|xutri|nesim|caret|jcirc|Jcirc|caron|twixt|ddarr|sccue|exist|jmath|sbquo|ngeqq|angst|ccaps|lceil|ngsim|UpTee|delta|Delta|rtrif|nharr|nhArr|nhpar|rtrie|jukcy|Jukcy|kappa|rsquo|Kappa|nlarr|nlArr|TSHcy|rrarr|aogon|Aogon|fflig|xrarr|tshcy|ccirc|nleqq|filig|upsih|nless|dharl|nlsim|fjlig|ropar|nltri|dharr|robrk|roarr|fllig|fltns|roang|rnmid|subnE|subne|lAarr|trisb|Ccirc|acirc|ccups|blank|VDash|forkv|Vdash|langd|cedil|blk12|blk14|laquo|strns|diams|notin|vDash|larrb|blk34|block|disin|uplus|vdash|vBarv|aelig|starf|Wedge|check|xrArr|lates|lbarr|lBarr|notni|lbbrk|bcong|frasl|lbrke|frown|vrtri|vprop|vnsup|gamma|Gamma|wedge|xodot|bdquo|srarr|doteq|ldquo|boxdl|boxdL|gcirc|Gcirc|boxDl|boxDL|boxdr|boxdR|boxDr|TRADE|trade|rlhar|boxDR|vnsub|npart|vltri|rlarr|boxhd|boxhD|nprec|gescc|nrarr|nrArr|boxHd|boxHD|boxhu|boxhU|nrtri|boxHu|clubs|boxHU|times|colon|Colon|gimel|xlArr|Tilde|nsime|tilde|nsmid|nspar|THORN|thorn|xlarr|nsube|nsubE|thkap|xhArr|comma|nsucc|boxul|boxuL|nsupe|nsupE|gneqq|gnsim|boxUl|boxUL|grave|boxur|boxuR|boxUr|boxUR|lescc|angle|bepsi|boxvh|varpi|boxvH|numsp|Theta|gsime|gsiml|theta|boxVh|boxVH|boxvl|gtcir|gtdot|boxvL|boxVl|boxVL|crarr|cross|Cross|nvsim|boxvr|nwarr|nwArr|sqsup|dtdot|Uogon|lhard|lharu|dtrif|ocirc|Ocirc|lhblk|duarr|odash|sqsub|Hacek|sqcup|llarr|duhar|oelig|OElig|ofcir|boxvR|uogon|lltri|boxVr|csube|uuarr|ohbar|csupe|ctdot|olarr|olcir|harrw|oline|sqcap|omacr|Omacr|omega|Omega|boxVR|aleph|lneqq|lnsim|loang|loarr|rharu|lobrk|hcirc|operp|oplus|rhard|Hcirc|orarr|Union|order|ecirc|Ecirc|cuepr|szlig|cuesc|breve|reals|eDDot|Breve|hoarr|lopar|utrif|rdquo|Umacr|umacr|efDot|swArr|ultri|alpha|rceil|ovbar|swarr|Wcirc|wcirc|smtes|smile|bsemi|lrarr|aring|parsl|lrhar|bsime|uhblk|lrtri|cupor|Aring|uharr|uharl|slarr|rbrke|bsolb|lsime|rbbrk|RBarr|lsimg|phone|rBarr|rbarr|icirc|lsquo|Icirc|emacr|Emacr|ratio|simne|plusb|simlE|simgE|simeq|pluse|ltcir|ltdot|empty|xharr|xdtri|iexcl|Alpha|ltrie|rarrw|pound|ltrif|xcirc|bumpe|prcue|bumpE|asymp|amacr|cuvee|Sigma|sigma|iiint|udhar|iiota|ijlig|IJlig|supnE|imacr|Imacr|prime|Prime|image|prnap|eogon|Eogon|rarrc|mdash|mDDot|cuwed|imath|supne|imped|Amacr|udarr|prsim|micro|rarrb|cwint|raquo|infin|eplus|range|rangd|Ucirc|radic|minus|amalg|veeeq|rAarr|epsiv|ycirc|quest|sharp|quot|zwnj|Qscr|race|qscr|Qopf|qopf|qint|rang|Rang|Zscr|zscr|Zopf|zopf|rarr|rArr|Rarr|Pscr|pscr|prop|prod|prnE|prec|ZHcy|zhcy|prap|Zeta|zeta|Popf|popf|Zdot|plus|zdot|Yuml|yuml|phiv|YUcy|yucy|Yscr|yscr|perp|Yopf|yopf|part|para|YIcy|Ouml|rcub|yicy|YAcy|rdca|ouml|osol|Oscr|rdsh|yacy|real|oscr|xvee|andd|rect|andv|Xscr|oror|ordm|ordf|xscr|ange|aopf|Aopf|rHar|Xopf|opar|Oopf|xopf|xnis|rhov|oopf|omid|xmap|oint|apid|apos|ogon|ascr|Ascr|odot|odiv|xcup|xcap|ocir|oast|nvlt|nvle|nvgt|nvge|nvap|Wscr|wscr|auml|ntlg|ntgl|nsup|nsub|nsim|Nscr|nscr|nsce|Wopf|ring|npre|wopf|npar|Auml|Barv|bbrk|Nopf|nopf|nmid|nLtv|beta|ropf|Ropf|Beta|beth|nles|rpar|nleq|bnot|bNot|nldr|NJcy|rscr|Rscr|Vscr|vscr|rsqb|njcy|bopf|nisd|Bopf|rtri|Vopf|nGtv|ngtr|vopf|boxh|boxH|boxv|nges|ngeq|boxV|bscr|scap|Bscr|bsim|Vert|vert|bsol|bull|bump|caps|cdot|ncup|scnE|ncap|nbsp|napE|Cdot|cent|sdot|Vbar|nang|vBar|chcy|Mscr|mscr|sect|semi|CHcy|Mopf|mopf|sext|circ|cire|mldr|mlcp|cirE|comp|shcy|SHcy|vArr|varr|cong|copf|Copf|copy|COPY|malt|male|macr|lvnE|cscr|ltri|sime|ltcc|simg|Cscr|siml|csub|Uuml|lsqb|lsim|uuml|csup|Lscr|lscr|utri|smid|lpar|cups|smte|lozf|darr|Lopf|Uscr|solb|lopf|sopf|Sopf|lneq|uscr|spar|dArr|lnap|Darr|dash|Sqrt|LJcy|ljcy|lHar|dHar|Upsi|upsi|diam|lesg|djcy|DJcy|leqq|dopf|Dopf|dscr|Dscr|dscy|ldsh|ldca|squf|DScy|sscr|Sscr|dsol|lcub|late|star|Star|Uopf|Larr|lArr|larr|uopf|dtri|dzcy|sube|subE|Lang|lang|Kscr|kscr|Kopf|kopf|KJcy|kjcy|KHcy|khcy|DZcy|ecir|edot|eDot|Jscr|jscr|succ|Jopf|jopf|Edot|uHar|emsp|ensp|Iuml|iuml|eopf|isin|Iscr|iscr|Eopf|epar|sung|epsi|escr|sup1|sup2|sup3|Iota|iota|supe|supE|Iopf|iopf|IOcy|iocy|Escr|esim|Esim|imof|Uarr|QUOT|uArr|uarr|euml|IEcy|iecy|Idot|Euml|euro|excl|Hscr|hscr|Hopf|hopf|TScy|tscy|Tscr|hbar|tscr|flat|tbrk|fnof|hArr|harr|half|fopf|Fopf|tdot|gvnE|fork|trie|gtcc|fscr|Fscr|gdot|gsim|Gscr|gscr|Gopf|gopf|gneq|Gdot|tosa|gnap|Topf|topf|geqq|toea|GJcy|gjcy|tint|gesl|mid|Sfr|ggg|top|ges|gla|glE|glj|geq|gne|gEl|gel|gnE|Gcy|gcy|gap|Tfr|tfr|Tcy|tcy|Hat|Tau|Ffr|tau|Tab|hfr|Hfr|ffr|Fcy|fcy|icy|Icy|iff|ETH|eth|ifr|Ifr|Eta|eta|int|Int|Sup|sup|ucy|Ucy|Sum|sum|jcy|ENG|ufr|Ufr|eng|Jcy|jfr|els|ell|egs|Efr|efr|Jfr|uml|kcy|Kcy|Ecy|ecy|kfr|Kfr|lap|Sub|sub|lat|lcy|Lcy|leg|Dot|dot|lEg|leq|les|squ|div|die|lfr|Lfr|lgE|Dfr|dfr|Del|deg|Dcy|dcy|lne|lnE|sol|loz|smt|Cup|lrm|cup|lsh|Lsh|sim|shy|map|Map|mcy|Mcy|mfr|Mfr|mho|gfr|Gfr|sfr|cir|Chi|chi|nap|Cfr|vcy|Vcy|cfr|Scy|scy|ncy|Ncy|vee|Vee|Cap|cap|nfr|scE|sce|Nfr|nge|ngE|nGg|vfr|Vfr|ngt|bot|nGt|nis|niv|Rsh|rsh|nle|nlE|bne|Bfr|bfr|nLl|nlt|nLt|Bcy|bcy|not|Not|rlm|wfr|Wfr|npr|nsc|num|ocy|ast|Ocy|ofr|xfr|Xfr|Ofr|ogt|ohm|apE|olt|Rho|ape|rho|Rfr|rfr|ord|REG|ang|reg|orv|And|and|AMP|Rcy|amp|Afr|ycy|Ycy|yen|yfr|Yfr|rcy|par|pcy|Pcy|pfr|Pfr|phi|Phi|afr|Acy|acy|zcy|Zcy|piv|acE|acd|zfr|Zfr|pre|prE|psi|Psi|qfr|Qfr|zwj|Or|ge|Gg|gt|gg|el|oS|lt|Lt|LT|Re|lg|gl|eg|ne|Im|it|le|DD|wp|wr|nu|Nu|dd|lE|Sc|sc|pi|Pi|ee|af|ll|Ll|rx|gE|xi|pm|Xi|ic|pr|Pr|in|ni|mp|mu|ac|Mu|or|ap|Gt|GT|ii);|&(Aacute|Agrave|Atilde|Ccedil|Eacute|Egrave|Iacute|Igrave|Ntilde|Oacute|Ograve|Oslash|Otilde|Uacute|Ugrave|Yacute|aacute|agrave|atilde|brvbar|ccedil|curren|divide|eacute|egrave|frac12|frac14|frac34|iacute|igrave|iquest|middot|ntilde|oacute|ograve|oslash|otilde|plusmn|uacute|ugrave|yacute|AElig|Acirc|Aring|Ecirc|Icirc|Ocirc|THORN|Ucirc|acirc|acute|aelig|aring|cedil|ecirc|icirc|iexcl|laquo|micro|ocirc|pound|raquo|szlig|thorn|times|ucirc|Auml|COPY|Euml|Iuml|Ouml|QUOT|Uuml|auml|cent|copy|euml|iuml|macr|nbsp|ordf|ordm|ouml|para|quot|sect|sup1|sup2|sup3|uuml|yuml|AMP|ETH|REG|amp|deg|eth|not|reg|shy|uml|yen|GT|LT|gt|lt)(?!;)([=a-zA-Z0-9]?)|([0-9]+)(;?)|[xX]([a-fA-F0-9]+)(;?)|&([0-9a-zA-Z]+)/g;
+ var decodeMap = {'aacute':'\xE1','Aacute':'\xC1','abreve':'\u0103','Abreve':'\u0102','ac':'\u223E','acd':'\u223F','acE':'\u223E\u0333','acirc':'\xE2','Acirc':'\xC2','acute':'\xB4','acy':'\u0430','Acy':'\u0410','aelig':'\xE6','AElig':'\xC6','af':'\u2061','afr':'\uD835\uDD1E','Afr':'\uD835\uDD04','agrave':'\xE0','Agrave':'\xC0','alefsym':'\u2135','aleph':'\u2135','alpha':'\u03B1','Alpha':'\u0391','amacr':'\u0101','Amacr':'\u0100','amalg':'\u2A3F','amp':'&','AMP':'&','and':'\u2227','And':'\u2A53','andand':'\u2A55','andd':'\u2A5C','andslope':'\u2A58','andv':'\u2A5A','ang':'\u2220','ange':'\u29A4','angle':'\u2220','angmsd':'\u2221','angmsdaa':'\u29A8','angmsdab':'\u29A9','angmsdac':'\u29AA','angmsdad':'\u29AB','angmsdae':'\u29AC','angmsdaf':'\u29AD','angmsdag':'\u29AE','angmsdah':'\u29AF','angrt':'\u221F','angrtvb':'\u22BE','angrtvbd':'\u299D','angsph':'\u2222','angst':'\xC5','angzarr':'\u237C','aogon':'\u0105','Aogon':'\u0104','aopf':'\uD835\uDD52','Aopf':'\uD835\uDD38','ap':'\u2248','apacir':'\u2A6F','ape':'\u224A','apE':'\u2A70','apid':'\u224B','apos':'\'','ApplyFunction':'\u2061','approx':'\u2248','approxeq':'\u224A','aring':'\xE5','Aring':'\xC5','ascr':'\uD835\uDCB6','Ascr':'\uD835\uDC9C','Assign':'\u2254','ast':'*','asymp':'\u2248','asympeq':'\u224D','atilde':'\xE3','Atilde':'\xC3','auml':'\xE4','Auml':'\xC4','awconint':'\u2233','awint':'\u2A11','backcong':'\u224C','backepsilon':'\u03F6','backprime':'\u2035','backsim':'\u223D','backsimeq':'\u22CD','Backslash':'\u2216','Barv':'\u2AE7','barvee':'\u22BD','barwed':'\u2305','Barwed':'\u2306','barwedge':'\u2305','bbrk':'\u23B5','bbrktbrk':'\u23B6','bcong':'\u224C','bcy':'\u0431','Bcy':'\u0411','bdquo':'\u201E','becaus':'\u2235','because':'\u2235','Because':'\u2235','bemptyv':'\u29B0','bepsi':'\u03F6','bernou':'\u212C','Bernoullis':'\u212C','beta':'\u03B2','Beta':'\u0392','beth':'\u2136','between':'\u226C','bfr':'\uD835\uDD1F','Bfr':'\uD835\uDD05','bigcap':'\u22C2','bigcirc':'\u25EF','bigcup':'\u22C3','bigodot':'\u2A00','bigoplus':'\u2A01','bigotimes':'\u2A02','bigsqcup':'\u2A06','bigstar':'\u2605','bigtriangledown':'\u25BD','bigtriangleup':'\u25B3','biguplus':'\u2A04','bigvee':'\u22C1','bigwedge':'\u22C0','bkarow':'\u290D','blacklozenge':'\u29EB','blacksquare':'\u25AA','blacktriangle':'\u25B4','blacktriangledown':'\u25BE','blacktriangleleft':'\u25C2','blacktriangleright':'\u25B8','blank':'\u2423','blk12':'\u2592','blk14':'\u2591','blk34':'\u2593','block':'\u2588','bne':'=\u20E5','bnequiv':'\u2261\u20E5','bnot':'\u2310','bNot':'\u2AED','bopf':'\uD835\uDD53','Bopf':'\uD835\uDD39','bot':'\u22A5','bottom':'\u22A5','bowtie':'\u22C8','boxbox':'\u29C9','boxdl':'\u2510','boxdL':'\u2555','boxDl':'\u2556','boxDL':'\u2557','boxdr':'\u250C','boxdR':'\u2552','boxDr':'\u2553','boxDR':'\u2554','boxh':'\u2500','boxH':'\u2550','boxhd':'\u252C','boxhD':'\u2565','boxHd':'\u2564','boxHD':'\u2566','boxhu':'\u2534','boxhU':'\u2568','boxHu':'\u2567','boxHU':'\u2569','boxminus':'\u229F','boxplus':'\u229E','boxtimes':'\u22A0','boxul':'\u2518','boxuL':'\u255B','boxUl':'\u255C','boxUL':'\u255D','boxur':'\u2514','boxuR':'\u2558','boxUr':'\u2559','boxUR':'\u255A','boxv':'\u2502','boxV':'\u2551','boxvh':'\u253C','boxvH':'\u256A','boxVh':'\u256B','boxVH':'\u256C','boxvl':'\u2524','boxvL':'\u2561','boxVl':'\u2562','boxVL':'\u2563','boxvr':'\u251C','boxvR':'\u255E','boxVr':'\u255F','boxVR':'\u2560','bprime':'\u2035','breve':'\u02D8','Breve':'\u02D8','brvbar':'\xA6','bscr':'\uD835\uDCB7','Bscr':'\u212C','bsemi':'\u204F','bsim':'\u223D','bsime':'\u22CD','bsol':'\\','bsolb':'\u29C5','bsolhsub':'\u27C8','bull':'\u2022','bullet':'\u2022','bump':'\u224E','bumpe':'\u224F','bumpE':'\u2AAE','bumpeq':'\u224F','Bumpeq':'\u224E','cacute':'\u0107','Cacute':'\u0106','cap':'\u2229','Cap':'\u22D2','capand':'\u2A44','capbrcup':'\u2A49','capcap':'\u2A4B','capcup':'\u2A47','capdot':'\u2A40','CapitalDifferentialD':'\u2145','caps':'\u2229\uFE00','caret':'\u2041','caron':'\u02C7','Cayleys':'\u212D','ccaps':'\u2A4D','ccaron':'\u010D','Ccaron':'\u010C','ccedil':'\xE7','Ccedil':'\xC7','ccirc':'\u0109','Ccirc':'\u0108','Cconint':'\u2230','ccups':'\u2A4C','ccupssm':'\u2A50','cdot':'\u010B','Cdot':'\u010A','cedil':'\xB8','Cedilla':'\xB8','cemptyv':'\u29B2','cent':'\xA2','centerdot':'\xB7','CenterDot':'\xB7','cfr':'\uD835\uDD20','Cfr':'\u212D','chcy':'\u0447','CHcy':'\u0427','check':'\u2713','checkmark':'\u2713','chi':'\u03C7','Chi':'\u03A7','cir':'\u25CB','circ':'\u02C6','circeq':'\u2257','circlearrowleft':'\u21BA','circlearrowright':'\u21BB','circledast':'\u229B','circledcirc':'\u229A','circleddash':'\u229D','CircleDot':'\u2299','circledR':'\xAE','circledS':'\u24C8','CircleMinus':'\u2296','CirclePlus':'\u2295','CircleTimes':'\u2297','cire':'\u2257','cirE':'\u29C3','cirfnint':'\u2A10','cirmid':'\u2AEF','cirscir':'\u29C2','ClockwiseContourIntegral':'\u2232','CloseCurlyDoubleQuote':'\u201D','CloseCurlyQuote':'\u2019','clubs':'\u2663','clubsuit':'\u2663','colon':':','Colon':'\u2237','colone':'\u2254','Colone':'\u2A74','coloneq':'\u2254','comma':',','commat':'@','comp':'\u2201','compfn':'\u2218','complement':'\u2201','complexes':'\u2102','cong':'\u2245','congdot':'\u2A6D','Congruent':'\u2261','conint':'\u222E','Conint':'\u222F','ContourIntegral':'\u222E','copf':'\uD835\uDD54','Copf':'\u2102','coprod':'\u2210','Coproduct':'\u2210','copy':'\xA9','COPY':'\xA9','copysr':'\u2117','CounterClockwiseContourIntegral':'\u2233','crarr':'\u21B5','cross':'\u2717','Cross':'\u2A2F','cscr':'\uD835\uDCB8','Cscr':'\uD835\uDC9E','csub':'\u2ACF','csube':'\u2AD1','csup':'\u2AD0','csupe':'\u2AD2','ctdot':'\u22EF','cudarrl':'\u2938','cudarrr':'\u2935','cuepr':'\u22DE','cuesc':'\u22DF','cularr':'\u21B6','cularrp':'\u293D','cup':'\u222A','Cup':'\u22D3','cupbrcap':'\u2A48','cupcap':'\u2A46','CupCap':'\u224D','cupcup':'\u2A4A','cupdot':'\u228D','cupor':'\u2A45','cups':'\u222A\uFE00','curarr':'\u21B7','curarrm':'\u293C','curlyeqprec':'\u22DE','curlyeqsucc':'\u22DF','curlyvee':'\u22CE','curlywedge':'\u22CF','curren':'\xA4','curvearrowleft':'\u21B6','curvearrowright':'\u21B7','cuvee':'\u22CE','cuwed':'\u22CF','cwconint':'\u2232','cwint':'\u2231','cylcty':'\u232D','dagger':'\u2020','Dagger':'\u2021','daleth':'\u2138','darr':'\u2193','dArr':'\u21D3','Darr':'\u21A1','dash':'\u2010','dashv':'\u22A3','Dashv':'\u2AE4','dbkarow':'\u290F','dblac':'\u02DD','dcaron':'\u010F','Dcaron':'\u010E','dcy':'\u0434','Dcy':'\u0414','dd':'\u2146','DD':'\u2145','ddagger':'\u2021','ddarr':'\u21CA','DDotrahd':'\u2911','ddotseq':'\u2A77','deg':'\xB0','Del':'\u2207','delta':'\u03B4','Delta':'\u0394','demptyv':'\u29B1','dfisht':'\u297F','dfr':'\uD835\uDD21','Dfr':'\uD835\uDD07','dHar':'\u2965','dharl':'\u21C3','dharr':'\u21C2','DiacriticalAcute':'\xB4','DiacriticalDot':'\u02D9','DiacriticalDoubleAcute':'\u02DD','DiacriticalGrave':'`','DiacriticalTilde':'\u02DC','diam':'\u22C4','diamond':'\u22C4','Diamond':'\u22C4','diamondsuit':'\u2666','diams':'\u2666','die':'\xA8','DifferentialD':'\u2146','digamma':'\u03DD','disin':'\u22F2','div':'\xF7','divide':'\xF7','divideontimes':'\u22C7','divonx':'\u22C7','djcy':'\u0452','DJcy':'\u0402','dlcorn':'\u231E','dlcrop':'\u230D','dollar':'$','dopf':'\uD835\uDD55','Dopf':'\uD835\uDD3B','dot':'\u02D9','Dot':'\xA8','DotDot':'\u20DC','doteq':'\u2250','doteqdot':'\u2251','DotEqual':'\u2250','dotminus':'\u2238','dotplus':'\u2214','dotsquare':'\u22A1','doublebarwedge':'\u2306','DoubleContourIntegral':'\u222F','DoubleDot':'\xA8','DoubleDownArrow':'\u21D3','DoubleLeftArrow':'\u21D0','DoubleLeftRightArrow':'\u21D4','DoubleLeftTee':'\u2AE4','DoubleLongLeftArrow':'\u27F8','DoubleLongLeftRightArrow':'\u27FA','DoubleLongRightArrow':'\u27F9','DoubleRightArrow':'\u21D2','DoubleRightTee':'\u22A8','DoubleUpArrow':'\u21D1','DoubleUpDownArrow':'\u21D5','DoubleVerticalBar':'\u2225','downarrow':'\u2193','Downarrow':'\u21D3','DownArrow':'\u2193','DownArrowBar':'\u2913','DownArrowUpArrow':'\u21F5','DownBreve':'\u0311','downdownarrows':'\u21CA','downharpoonleft':'\u21C3','downharpoonright':'\u21C2','DownLeftRightVector':'\u2950','DownLeftTeeVector':'\u295E','DownLeftVector':'\u21BD','DownLeftVectorBar':'\u2956','DownRightTeeVector':'\u295F','DownRightVector':'\u21C1','DownRightVectorBar':'\u2957','DownTee':'\u22A4','DownTeeArrow':'\u21A7','drbkarow':'\u2910','drcorn':'\u231F','drcrop':'\u230C','dscr':'\uD835\uDCB9','Dscr':'\uD835\uDC9F','dscy':'\u0455','DScy':'\u0405','dsol':'\u29F6','dstrok':'\u0111','Dstrok':'\u0110','dtdot':'\u22F1','dtri':'\u25BF','dtrif':'\u25BE','duarr':'\u21F5','duhar':'\u296F','dwangle':'\u29A6','dzcy':'\u045F','DZcy':'\u040F','dzigrarr':'\u27FF','eacute':'\xE9','Eacute':'\xC9','easter':'\u2A6E','ecaron':'\u011B','Ecaron':'\u011A','ecir':'\u2256','ecirc':'\xEA','Ecirc':'\xCA','ecolon':'\u2255','ecy':'\u044D','Ecy':'\u042D','eDDot':'\u2A77','edot':'\u0117','eDot':'\u2251','Edot':'\u0116','ee':'\u2147','efDot':'\u2252','efr':'\uD835\uDD22','Efr':'\uD835\uDD08','eg':'\u2A9A','egrave':'\xE8','Egrave':'\xC8','egs':'\u2A96','egsdot':'\u2A98','el':'\u2A99','Element':'\u2208','elinters':'\u23E7','ell':'\u2113','els':'\u2A95','elsdot':'\u2A97','emacr':'\u0113','Emacr':'\u0112','empty':'\u2205','emptyset':'\u2205','EmptySmallSquare':'\u25FB','emptyv':'\u2205','EmptyVerySmallSquare':'\u25AB','emsp':'\u2003','emsp13':'\u2004','emsp14':'\u2005','eng':'\u014B','ENG':'\u014A','ensp':'\u2002','eogon':'\u0119','Eogon':'\u0118','eopf':'\uD835\uDD56','Eopf':'\uD835\uDD3C','epar':'\u22D5','eparsl':'\u29E3','eplus':'\u2A71','epsi':'\u03B5','epsilon':'\u03B5','Epsilon':'\u0395','epsiv':'\u03F5','eqcirc':'\u2256','eqcolon':'\u2255','eqsim':'\u2242','eqslantgtr':'\u2A96','eqslantless':'\u2A95','Equal':'\u2A75','equals':'=','EqualTilde':'\u2242','equest':'\u225F','Equilibrium':'\u21CC','equiv':'\u2261','equivDD':'\u2A78','eqvparsl':'\u29E5','erarr':'\u2971','erDot':'\u2253','escr':'\u212F','Escr':'\u2130','esdot':'\u2250','esim':'\u2242','Esim':'\u2A73','eta':'\u03B7','Eta':'\u0397','eth':'\xF0','ETH':'\xD0','euml':'\xEB','Euml':'\xCB','euro':'\u20AC','excl':'!','exist':'\u2203','Exists':'\u2203','expectation':'\u2130','exponentiale':'\u2147','ExponentialE':'\u2147','fallingdotseq':'\u2252','fcy':'\u0444','Fcy':'\u0424','female':'\u2640','ffilig':'\uFB03','fflig':'\uFB00','ffllig':'\uFB04','ffr':'\uD835\uDD23','Ffr':'\uD835\uDD09','filig':'\uFB01','FilledSmallSquare':'\u25FC','FilledVerySmallSquare':'\u25AA','fjlig':'fj','flat':'\u266D','fllig':'\uFB02','fltns':'\u25B1','fnof':'\u0192','fopf':'\uD835\uDD57','Fopf':'\uD835\uDD3D','forall':'\u2200','ForAll':'\u2200','fork':'\u22D4','forkv':'\u2AD9','Fouriertrf':'\u2131','fpartint':'\u2A0D','frac12':'\xBD','frac13':'\u2153','frac14':'\xBC','frac15':'\u2155','frac16':'\u2159','frac18':'\u215B','frac23':'\u2154','frac25':'\u2156','frac34':'\xBE','frac35':'\u2157','frac38':'\u215C','frac45':'\u2158','frac56':'\u215A','frac58':'\u215D','frac78':'\u215E','frasl':'\u2044','frown':'\u2322','fscr':'\uD835\uDCBB','Fscr':'\u2131','gacute':'\u01F5','gamma':'\u03B3','Gamma':'\u0393','gammad':'\u03DD','Gammad':'\u03DC','gap':'\u2A86','gbreve':'\u011F','Gbreve':'\u011E','Gcedil':'\u0122','gcirc':'\u011D','Gcirc':'\u011C','gcy':'\u0433','Gcy':'\u0413','gdot':'\u0121','Gdot':'\u0120','ge':'\u2265','gE':'\u2267','gel':'\u22DB','gEl':'\u2A8C','geq':'\u2265','geqq':'\u2267','geqslant':'\u2A7E','ges':'\u2A7E','gescc':'\u2AA9','gesdot':'\u2A80','gesdoto':'\u2A82','gesdotol':'\u2A84','gesl':'\u22DB\uFE00','gesles':'\u2A94','gfr':'\uD835\uDD24','Gfr':'\uD835\uDD0A','gg':'\u226B','Gg':'\u22D9','ggg':'\u22D9','gimel':'\u2137','gjcy':'\u0453','GJcy':'\u0403','gl':'\u2277','gla':'\u2AA5','glE':'\u2A92','glj':'\u2AA4','gnap':'\u2A8A','gnapprox':'\u2A8A','gne':'\u2A88','gnE':'\u2269','gneq':'\u2A88','gneqq':'\u2269','gnsim':'\u22E7','gopf':'\uD835\uDD58','Gopf':'\uD835\uDD3E','grave':'`','GreaterEqual':'\u2265','GreaterEqualLess':'\u22DB','GreaterFullEqual':'\u2267','GreaterGreater':'\u2AA2','GreaterLess':'\u2277','GreaterSlantEqual':'\u2A7E','GreaterTilde':'\u2273','gscr':'\u210A','Gscr':'\uD835\uDCA2','gsim':'\u2273','gsime':'\u2A8E','gsiml':'\u2A90','gt':'>','Gt':'\u226B','GT':'>','gtcc':'\u2AA7','gtcir':'\u2A7A','gtdot':'\u22D7','gtlPar':'\u2995','gtquest':'\u2A7C','gtrapprox':'\u2A86','gtrarr':'\u2978','gtrdot':'\u22D7','gtreqless':'\u22DB','gtreqqless':'\u2A8C','gtrless':'\u2277','gtrsim':'\u2273','gvertneqq':'\u2269\uFE00','gvnE':'\u2269\uFE00','Hacek':'\u02C7','hairsp':'\u200A','half':'\xBD','hamilt':'\u210B','hardcy':'\u044A','HARDcy':'\u042A','harr':'\u2194','hArr':'\u21D4','harrcir':'\u2948','harrw':'\u21AD','Hat':'^','hbar':'\u210F','hcirc':'\u0125','Hcirc':'\u0124','hearts':'\u2665','heartsuit':'\u2665','hellip':'\u2026','hercon':'\u22B9','hfr':'\uD835\uDD25','Hfr':'\u210C','HilbertSpace':'\u210B','hksearow':'\u2925','hkswarow':'\u2926','hoarr':'\u21FF','homtht':'\u223B','hookleftarrow':'\u21A9','hookrightarrow':'\u21AA','hopf':'\uD835\uDD59','Hopf':'\u210D','horbar':'\u2015','HorizontalLine':'\u2500','hscr':'\uD835\uDCBD','Hscr':'\u210B','hslash':'\u210F','hstrok':'\u0127','Hstrok':'\u0126','HumpDownHump':'\u224E','HumpEqual':'\u224F','hybull':'\u2043','hyphen':'\u2010','iacute':'\xED','Iacute':'\xCD','ic':'\u2063','icirc':'\xEE','Icirc':'\xCE','icy':'\u0438','Icy':'\u0418','Idot':'\u0130','iecy':'\u0435','IEcy':'\u0415','iexcl':'\xA1','iff':'\u21D4','ifr':'\uD835\uDD26','Ifr':'\u2111','igrave':'\xEC','Igrave':'\xCC','ii':'\u2148','iiiint':'\u2A0C','iiint':'\u222D','iinfin':'\u29DC','iiota':'\u2129','ijlig':'\u0133','IJlig':'\u0132','Im':'\u2111','imacr':'\u012B','Imacr':'\u012A','image':'\u2111','ImaginaryI':'\u2148','imagline':'\u2110','imagpart':'\u2111','imath':'\u0131','imof':'\u22B7','imped':'\u01B5','Implies':'\u21D2','in':'\u2208','incare':'\u2105','infin':'\u221E','infintie':'\u29DD','inodot':'\u0131','int':'\u222B','Int':'\u222C','intcal':'\u22BA','integers':'\u2124','Integral':'\u222B','intercal':'\u22BA','Intersection':'\u22C2','intlarhk':'\u2A17','intprod':'\u2A3C','InvisibleComma':'\u2063','InvisibleTimes':'\u2062','iocy':'\u0451','IOcy':'\u0401','iogon':'\u012F','Iogon':'\u012E','iopf':'\uD835\uDD5A','Iopf':'\uD835\uDD40','iota':'\u03B9','Iota':'\u0399','iprod':'\u2A3C','iquest':'\xBF','iscr':'\uD835\uDCBE','Iscr':'\u2110','isin':'\u2208','isindot':'\u22F5','isinE':'\u22F9','isins':'\u22F4','isinsv':'\u22F3','isinv':'\u2208','it':'\u2062','itilde':'\u0129','Itilde':'\u0128','iukcy':'\u0456','Iukcy':'\u0406','iuml':'\xEF','Iuml':'\xCF','jcirc':'\u0135','Jcirc':'\u0134','jcy':'\u0439','Jcy':'\u0419','jfr':'\uD835\uDD27','Jfr':'\uD835\uDD0D','jmath':'\u0237','jopf':'\uD835\uDD5B','Jopf':'\uD835\uDD41','jscr':'\uD835\uDCBF','Jscr':'\uD835\uDCA5','jsercy':'\u0458','Jsercy':'\u0408','jukcy':'\u0454','Jukcy':'\u0404','kappa':'\u03BA','Kappa':'\u039A','kappav':'\u03F0','kcedil':'\u0137','Kcedil':'\u0136','kcy':'\u043A','Kcy':'\u041A','kfr':'\uD835\uDD28','Kfr':'\uD835\uDD0E','kgreen':'\u0138','khcy':'\u0445','KHcy':'\u0425','kjcy':'\u045C','KJcy':'\u040C','kopf':'\uD835\uDD5C','Kopf':'\uD835\uDD42','kscr':'\uD835\uDCC0','Kscr':'\uD835\uDCA6','lAarr':'\u21DA','lacute':'\u013A','Lacute':'\u0139','laemptyv':'\u29B4','lagran':'\u2112','lambda':'\u03BB','Lambda':'\u039B','lang':'\u27E8','Lang':'\u27EA','langd':'\u2991','langle':'\u27E8','lap':'\u2A85','Laplacetrf':'\u2112','laquo':'\xAB','larr':'\u2190','lArr':'\u21D0','Larr':'\u219E','larrb':'\u21E4','larrbfs':'\u291F','larrfs':'\u291D','larrhk':'\u21A9','larrlp':'\u21AB','larrpl':'\u2939','larrsim':'\u2973','larrtl':'\u21A2','lat':'\u2AAB','latail':'\u2919','lAtail':'\u291B','late':'\u2AAD','lates':'\u2AAD\uFE00','lbarr':'\u290C','lBarr':'\u290E','lbbrk':'\u2772','lbrace':'{','lbrack':'[','lbrke':'\u298B','lbrksld':'\u298F','lbrkslu':'\u298D','lcaron':'\u013E','Lcaron':'\u013D','lcedil':'\u013C','Lcedil':'\u013B','lceil':'\u2308','lcub':'{','lcy':'\u043B','Lcy':'\u041B','ldca':'\u2936','ldquo':'\u201C','ldquor':'\u201E','ldrdhar':'\u2967','ldrushar':'\u294B','ldsh':'\u21B2','le':'\u2264','lE':'\u2266','LeftAngleBracket':'\u27E8','leftarrow':'\u2190','Leftarrow':'\u21D0','LeftArrow':'\u2190','LeftArrowBar':'\u21E4','LeftArrowRightArrow':'\u21C6','leftarrowtail':'\u21A2','LeftCeiling':'\u2308','LeftDoubleBracket':'\u27E6','LeftDownTeeVector':'\u2961','LeftDownVector':'\u21C3','LeftDownVectorBar':'\u2959','LeftFloor':'\u230A','leftharpoondown':'\u21BD','leftharpoonup':'\u21BC','leftleftarrows':'\u21C7','leftrightarrow':'\u2194','Leftrightarrow':'\u21D4','LeftRightArrow':'\u2194','leftrightarrows':'\u21C6','leftrightharpoons':'\u21CB','leftrightsquigarrow':'\u21AD','LeftRightVector':'\u294E','LeftTee':'\u22A3','LeftTeeArrow':'\u21A4','LeftTeeVector':'\u295A','leftthreetimes':'\u22CB','LeftTriangle':'\u22B2','LeftTriangleBar':'\u29CF','LeftTriangleEqual':'\u22B4','LeftUpDownVector':'\u2951','LeftUpTeeVector':'\u2960','LeftUpVector':'\u21BF','LeftUpVectorBar':'\u2958','LeftVector':'\u21BC','LeftVectorBar':'\u2952','leg':'\u22DA','lEg':'\u2A8B','leq':'\u2264','leqq':'\u2266','leqslant':'\u2A7D','les':'\u2A7D','lescc':'\u2AA8','lesdot':'\u2A7F','lesdoto':'\u2A81','lesdotor':'\u2A83','lesg':'\u22DA\uFE00','lesges':'\u2A93','lessapprox':'\u2A85','lessdot':'\u22D6','lesseqgtr':'\u22DA','lesseqqgtr':'\u2A8B','LessEqualGreater':'\u22DA','LessFullEqual':'\u2266','LessGreater':'\u2276','lessgtr':'\u2276','LessLess':'\u2AA1','lesssim':'\u2272','LessSlantEqual':'\u2A7D','LessTilde':'\u2272','lfisht':'\u297C','lfloor':'\u230A','lfr':'\uD835\uDD29','Lfr':'\uD835\uDD0F','lg':'\u2276','lgE':'\u2A91','lHar':'\u2962','lhard':'\u21BD','lharu':'\u21BC','lharul':'\u296A','lhblk':'\u2584','ljcy':'\u0459','LJcy':'\u0409','ll':'\u226A','Ll':'\u22D8','llarr':'\u21C7','llcorner':'\u231E','Lleftarrow':'\u21DA','llhard':'\u296B','lltri':'\u25FA','lmidot':'\u0140','Lmidot':'\u013F','lmoust':'\u23B0','lmoustache':'\u23B0','lnap':'\u2A89','lnapprox':'\u2A89','lne':'\u2A87','lnE':'\u2268','lneq':'\u2A87','lneqq':'\u2268','lnsim':'\u22E6','loang':'\u27EC','loarr':'\u21FD','lobrk':'\u27E6','longleftarrow':'\u27F5','Longleftarrow':'\u27F8','LongLeftArrow':'\u27F5','longleftrightarrow':'\u27F7','Longleftrightarrow':'\u27FA','LongLeftRightArrow':'\u27F7','longmapsto':'\u27FC','longrightarrow':'\u27F6','Longrightarrow':'\u27F9','LongRightArrow':'\u27F6','looparrowleft':'\u21AB','looparrowright':'\u21AC','lopar':'\u2985','lopf':'\uD835\uDD5D','Lopf':'\uD835\uDD43','loplus':'\u2A2D','lotimes':'\u2A34','lowast':'\u2217','lowbar':'_','LowerLeftArrow':'\u2199','LowerRightArrow':'\u2198','loz':'\u25CA','lozenge':'\u25CA','lozf':'\u29EB','lpar':'(','lparlt':'\u2993','lrarr':'\u21C6','lrcorner':'\u231F','lrhar':'\u21CB','lrhard':'\u296D','lrm':'\u200E','lrtri':'\u22BF','lsaquo':'\u2039','lscr':'\uD835\uDCC1','Lscr':'\u2112','lsh':'\u21B0','Lsh':'\u21B0','lsim':'\u2272','lsime':'\u2A8D','lsimg':'\u2A8F','lsqb':'[','lsquo':'\u2018','lsquor':'\u201A','lstrok':'\u0142','Lstrok':'\u0141','lt':'<','Lt':'\u226A','LT':'<','ltcc':'\u2AA6','ltcir':'\u2A79','ltdot':'\u22D6','lthree':'\u22CB','ltimes':'\u22C9','ltlarr':'\u2976','ltquest':'\u2A7B','ltri':'\u25C3','ltrie':'\u22B4','ltrif':'\u25C2','ltrPar':'\u2996','lurdshar':'\u294A','luruhar':'\u2966','lvertneqq':'\u2268\uFE00','lvnE':'\u2268\uFE00','macr':'\xAF','male':'\u2642','malt':'\u2720','maltese':'\u2720','map':'\u21A6','Map':'\u2905','mapsto':'\u21A6','mapstodown':'\u21A7','mapstoleft':'\u21A4','mapstoup':'\u21A5','marker':'\u25AE','mcomma':'\u2A29','mcy':'\u043C','Mcy':'\u041C','mdash':'\u2014','mDDot':'\u223A','measuredangle':'\u2221','MediumSpace':'\u205F','Mellintrf':'\u2133','mfr':'\uD835\uDD2A','Mfr':'\uD835\uDD10','mho':'\u2127','micro':'\xB5','mid':'\u2223','midast':'*','midcir':'\u2AF0','middot':'\xB7','minus':'\u2212','minusb':'\u229F','minusd':'\u2238','minusdu':'\u2A2A','MinusPlus':'\u2213','mlcp':'\u2ADB','mldr':'\u2026','mnplus':'\u2213','models':'\u22A7','mopf':'\uD835\uDD5E','Mopf':'\uD835\uDD44','mp':'\u2213','mscr':'\uD835\uDCC2','Mscr':'\u2133','mstpos':'\u223E','mu':'\u03BC','Mu':'\u039C','multimap':'\u22B8','mumap':'\u22B8','nabla':'\u2207','nacute':'\u0144','Nacute':'\u0143','nang':'\u2220\u20D2','nap':'\u2249','napE':'\u2A70\u0338','napid':'\u224B\u0338','napos':'\u0149','napprox':'\u2249','natur':'\u266E','natural':'\u266E','naturals':'\u2115','nbsp':'\xA0','nbump':'\u224E\u0338','nbumpe':'\u224F\u0338','ncap':'\u2A43','ncaron':'\u0148','Ncaron':'\u0147','ncedil':'\u0146','Ncedil':'\u0145','ncong':'\u2247','ncongdot':'\u2A6D\u0338','ncup':'\u2A42','ncy':'\u043D','Ncy':'\u041D','ndash':'\u2013','ne':'\u2260','nearhk':'\u2924','nearr':'\u2197','neArr':'\u21D7','nearrow':'\u2197','nedot':'\u2250\u0338','NegativeMediumSpace':'\u200B','NegativeThickSpace':'\u200B','NegativeThinSpace':'\u200B','NegativeVeryThinSpace':'\u200B','nequiv':'\u2262','nesear':'\u2928','nesim':'\u2242\u0338','NestedGreaterGreater':'\u226B','NestedLessLess':'\u226A','NewLine':'\n','nexist':'\u2204','nexists':'\u2204','nfr':'\uD835\uDD2B','Nfr':'\uD835\uDD11','nge':'\u2271','ngE':'\u2267\u0338','ngeq':'\u2271','ngeqq':'\u2267\u0338','ngeqslant':'\u2A7E\u0338','nges':'\u2A7E\u0338','nGg':'\u22D9\u0338','ngsim':'\u2275','ngt':'\u226F','nGt':'\u226B\u20D2','ngtr':'\u226F','nGtv':'\u226B\u0338','nharr':'\u21AE','nhArr':'\u21CE','nhpar':'\u2AF2','ni':'\u220B','nis':'\u22FC','nisd':'\u22FA','niv':'\u220B','njcy':'\u045A','NJcy':'\u040A','nlarr':'\u219A','nlArr':'\u21CD','nldr':'\u2025','nle':'\u2270','nlE':'\u2266\u0338','nleftarrow':'\u219A','nLeftarrow':'\u21CD','nleftrightarrow':'\u21AE','nLeftrightarrow':'\u21CE','nleq':'\u2270','nleqq':'\u2266\u0338','nleqslant':'\u2A7D\u0338','nles':'\u2A7D\u0338','nless':'\u226E','nLl':'\u22D8\u0338','nlsim':'\u2274','nlt':'\u226E','nLt':'\u226A\u20D2','nltri':'\u22EA','nltrie':'\u22EC','nLtv':'\u226A\u0338','nmid':'\u2224','NoBreak':'\u2060','NonBreakingSpace':'\xA0','nopf':'\uD835\uDD5F','Nopf':'\u2115','not':'\xAC','Not':'\u2AEC','NotCongruent':'\u2262','NotCupCap':'\u226D','NotDoubleVerticalBar':'\u2226','NotElement':'\u2209','NotEqual':'\u2260','NotEqualTilde':'\u2242\u0338','NotExists':'\u2204','NotGreater':'\u226F','NotGreaterEqual':'\u2271','NotGreaterFullEqual':'\u2267\u0338','NotGreaterGreater':'\u226B\u0338','NotGreaterLess':'\u2279','NotGreaterSlantEqual':'\u2A7E\u0338','NotGreaterTilde':'\u2275','NotHumpDownHump':'\u224E\u0338','NotHumpEqual':'\u224F\u0338','notin':'\u2209','notindot':'\u22F5\u0338','notinE':'\u22F9\u0338','notinva':'\u2209','notinvb':'\u22F7','notinvc':'\u22F6','NotLeftTriangle':'\u22EA','NotLeftTriangleBar':'\u29CF\u0338','NotLeftTriangleEqual':'\u22EC','NotLess':'\u226E','NotLessEqual':'\u2270','NotLessGreater':'\u2278','NotLessLess':'\u226A\u0338','NotLessSlantEqual':'\u2A7D\u0338','NotLessTilde':'\u2274','NotNestedGreaterGreater':'\u2AA2\u0338','NotNestedLessLess':'\u2AA1\u0338','notni':'\u220C','notniva':'\u220C','notnivb':'\u22FE','notnivc':'\u22FD','NotPrecedes':'\u2280','NotPrecedesEqual':'\u2AAF\u0338','NotPrecedesSlantEqual':'\u22E0','NotReverseElement':'\u220C','NotRightTriangle':'\u22EB','NotRightTriangleBar':'\u29D0\u0338','NotRightTriangleEqual':'\u22ED','NotSquareSubset':'\u228F\u0338','NotSquareSubsetEqual':'\u22E2','NotSquareSuperset':'\u2290\u0338','NotSquareSupersetEqual':'\u22E3','NotSubset':'\u2282\u20D2','NotSubsetEqual':'\u2288','NotSucceeds':'\u2281','NotSucceedsEqual':'\u2AB0\u0338','NotSucceedsSlantEqual':'\u22E1','NotSucceedsTilde':'\u227F\u0338','NotSuperset':'\u2283\u20D2','NotSupersetEqual':'\u2289','NotTilde':'\u2241','NotTildeEqual':'\u2244','NotTildeFullEqual':'\u2247','NotTildeTilde':'\u2249','NotVerticalBar':'\u2224','npar':'\u2226','nparallel':'\u2226','nparsl':'\u2AFD\u20E5','npart':'\u2202\u0338','npolint':'\u2A14','npr':'\u2280','nprcue':'\u22E0','npre':'\u2AAF\u0338','nprec':'\u2280','npreceq':'\u2AAF\u0338','nrarr':'\u219B','nrArr':'\u21CF','nrarrc':'\u2933\u0338','nrarrw':'\u219D\u0338','nrightarrow':'\u219B','nRightarrow':'\u21CF','nrtri':'\u22EB','nrtrie':'\u22ED','nsc':'\u2281','nsccue':'\u22E1','nsce':'\u2AB0\u0338','nscr':'\uD835\uDCC3','Nscr':'\uD835\uDCA9','nshortmid':'\u2224','nshortparallel':'\u2226','nsim':'\u2241','nsime':'\u2244','nsimeq':'\u2244','nsmid':'\u2224','nspar':'\u2226','nsqsube':'\u22E2','nsqsupe':'\u22E3','nsub':'\u2284','nsube':'\u2288','nsubE':'\u2AC5\u0338','nsubset':'\u2282\u20D2','nsubseteq':'\u2288','nsubseteqq':'\u2AC5\u0338','nsucc':'\u2281','nsucceq':'\u2AB0\u0338','nsup':'\u2285','nsupe':'\u2289','nsupE':'\u2AC6\u0338','nsupset':'\u2283\u20D2','nsupseteq':'\u2289','nsupseteqq':'\u2AC6\u0338','ntgl':'\u2279','ntilde':'\xF1','Ntilde':'\xD1','ntlg':'\u2278','ntriangleleft':'\u22EA','ntrianglelefteq':'\u22EC','ntriangleright':'\u22EB','ntrianglerighteq':'\u22ED','nu':'\u03BD','Nu':'\u039D','num':'#','numero':'\u2116','numsp':'\u2007','nvap':'\u224D\u20D2','nvdash':'\u22AC','nvDash':'\u22AD','nVdash':'\u22AE','nVDash':'\u22AF','nvge':'\u2265\u20D2','nvgt':'>\u20D2','nvHarr':'\u2904','nvinfin':'\u29DE','nvlArr':'\u2902','nvle':'\u2264\u20D2','nvlt':'<\u20D2','nvltrie':'\u22B4\u20D2','nvrArr':'\u2903','nvrtrie':'\u22B5\u20D2','nvsim':'\u223C\u20D2','nwarhk':'\u2923','nwarr':'\u2196','nwArr':'\u21D6','nwarrow':'\u2196','nwnear':'\u2927','oacute':'\xF3','Oacute':'\xD3','oast':'\u229B','ocir':'\u229A','ocirc':'\xF4','Ocirc':'\xD4','ocy':'\u043E','Ocy':'\u041E','odash':'\u229D','odblac':'\u0151','Odblac':'\u0150','odiv':'\u2A38','odot':'\u2299','odsold':'\u29BC','oelig':'\u0153','OElig':'\u0152','ofcir':'\u29BF','ofr':'\uD835\uDD2C','Ofr':'\uD835\uDD12','ogon':'\u02DB','ograve':'\xF2','Ograve':'\xD2','ogt':'\u29C1','ohbar':'\u29B5','ohm':'\u03A9','oint':'\u222E','olarr':'\u21BA','olcir':'\u29BE','olcross':'\u29BB','oline':'\u203E','olt':'\u29C0','omacr':'\u014D','Omacr':'\u014C','omega':'\u03C9','Omega':'\u03A9','omicron':'\u03BF','Omicron':'\u039F','omid':'\u29B6','ominus':'\u2296','oopf':'\uD835\uDD60','Oopf':'\uD835\uDD46','opar':'\u29B7','OpenCurlyDoubleQuote':'\u201C','OpenCurlyQuote':'\u2018','operp':'\u29B9','oplus':'\u2295','or':'\u2228','Or':'\u2A54','orarr':'\u21BB','ord':'\u2A5D','order':'\u2134','orderof':'\u2134','ordf':'\xAA','ordm':'\xBA','origof':'\u22B6','oror':'\u2A56','orslope':'\u2A57','orv':'\u2A5B','oS':'\u24C8','oscr':'\u2134','Oscr':'\uD835\uDCAA','oslash':'\xF8','Oslash':'\xD8','osol':'\u2298','otilde':'\xF5','Otilde':'\xD5','otimes':'\u2297','Otimes':'\u2A37','otimesas':'\u2A36','ouml':'\xF6','Ouml':'\xD6','ovbar':'\u233D','OverBar':'\u203E','OverBrace':'\u23DE','OverBracket':'\u23B4','OverParenthesis':'\u23DC','par':'\u2225','para':'\xB6','parallel':'\u2225','parsim':'\u2AF3','parsl':'\u2AFD','part':'\u2202','PartialD':'\u2202','pcy':'\u043F','Pcy':'\u041F','percnt':'%','period':'.','permil':'\u2030','perp':'\u22A5','pertenk':'\u2031','pfr':'\uD835\uDD2D','Pfr':'\uD835\uDD13','phi':'\u03C6','Phi':'\u03A6','phiv':'\u03D5','phmmat':'\u2133','phone':'\u260E','pi':'\u03C0','Pi':'\u03A0','pitchfork':'\u22D4','piv':'\u03D6','planck':'\u210F','planckh':'\u210E','plankv':'\u210F','plus':'+','plusacir':'\u2A23','plusb':'\u229E','pluscir':'\u2A22','plusdo':'\u2214','plusdu':'\u2A25','pluse':'\u2A72','PlusMinus':'\xB1','plusmn':'\xB1','plussim':'\u2A26','plustwo':'\u2A27','pm':'\xB1','Poincareplane':'\u210C','pointint':'\u2A15','popf':'\uD835\uDD61','Popf':'\u2119','pound':'\xA3','pr':'\u227A','Pr':'\u2ABB','prap':'\u2AB7','prcue':'\u227C','pre':'\u2AAF','prE':'\u2AB3','prec':'\u227A','precapprox':'\u2AB7','preccurlyeq':'\u227C','Precedes':'\u227A','PrecedesEqual':'\u2AAF','PrecedesSlantEqual':'\u227C','PrecedesTilde':'\u227E','preceq':'\u2AAF','precnapprox':'\u2AB9','precneqq':'\u2AB5','precnsim':'\u22E8','precsim':'\u227E','prime':'\u2032','Prime':'\u2033','primes':'\u2119','prnap':'\u2AB9','prnE':'\u2AB5','prnsim':'\u22E8','prod':'\u220F','Product':'\u220F','profalar':'\u232E','profline':'\u2312','profsurf':'\u2313','prop':'\u221D','Proportion':'\u2237','Proportional':'\u221D','propto':'\u221D','prsim':'\u227E','prurel':'\u22B0','pscr':'\uD835\uDCC5','Pscr':'\uD835\uDCAB','psi':'\u03C8','Psi':'\u03A8','puncsp':'\u2008','qfr':'\uD835\uDD2E','Qfr':'\uD835\uDD14','qint':'\u2A0C','qopf':'\uD835\uDD62','Qopf':'\u211A','qprime':'\u2057','qscr':'\uD835\uDCC6','Qscr':'\uD835\uDCAC','quaternions':'\u210D','quatint':'\u2A16','quest':'?','questeq':'\u225F','quot':'"','QUOT':'"','rAarr':'\u21DB','race':'\u223D\u0331','racute':'\u0155','Racute':'\u0154','radic':'\u221A','raemptyv':'\u29B3','rang':'\u27E9','Rang':'\u27EB','rangd':'\u2992','range':'\u29A5','rangle':'\u27E9','raquo':'\xBB','rarr':'\u2192','rArr':'\u21D2','Rarr':'\u21A0','rarrap':'\u2975','rarrb':'\u21E5','rarrbfs':'\u2920','rarrc':'\u2933','rarrfs':'\u291E','rarrhk':'\u21AA','rarrlp':'\u21AC','rarrpl':'\u2945','rarrsim':'\u2974','rarrtl':'\u21A3','Rarrtl':'\u2916','rarrw':'\u219D','ratail':'\u291A','rAtail':'\u291C','ratio':'\u2236','rationals':'\u211A','rbarr':'\u290D','rBarr':'\u290F','RBarr':'\u2910','rbbrk':'\u2773','rbrace':'}','rbrack':']','rbrke':'\u298C','rbrksld':'\u298E','rbrkslu':'\u2990','rcaron':'\u0159','Rcaron':'\u0158','rcedil':'\u0157','Rcedil':'\u0156','rceil':'\u2309','rcub':'}','rcy':'\u0440','Rcy':'\u0420','rdca':'\u2937','rdldhar':'\u2969','rdquo':'\u201D','rdquor':'\u201D','rdsh':'\u21B3','Re':'\u211C','real':'\u211C','realine':'\u211B','realpart':'\u211C','reals':'\u211D','rect':'\u25AD','reg':'\xAE','REG':'\xAE','ReverseElement':'\u220B','ReverseEquilibrium':'\u21CB','ReverseUpEquilibrium':'\u296F','rfisht':'\u297D','rfloor':'\u230B','rfr':'\uD835\uDD2F','Rfr':'\u211C','rHar':'\u2964','rhard':'\u21C1','rharu':'\u21C0','rharul':'\u296C','rho':'\u03C1','Rho':'\u03A1','rhov':'\u03F1','RightAngleBracket':'\u27E9','rightarrow':'\u2192','Rightarrow':'\u21D2','RightArrow':'\u2192','RightArrowBar':'\u21E5','RightArrowLeftArrow':'\u21C4','rightarrowtail':'\u21A3','RightCeiling':'\u2309','RightDoubleBracket':'\u27E7','RightDownTeeVector':'\u295D','RightDownVector':'\u21C2','RightDownVectorBar':'\u2955','RightFloor':'\u230B','rightharpoondown':'\u21C1','rightharpoonup':'\u21C0','rightleftarrows':'\u21C4','rightleftharpoons':'\u21CC','rightrightarrows':'\u21C9','rightsquigarrow':'\u219D','RightTee':'\u22A2','RightTeeArrow':'\u21A6','RightTeeVector':'\u295B','rightthreetimes':'\u22CC','RightTriangle':'\u22B3','RightTriangleBar':'\u29D0','RightTriangleEqual':'\u22B5','RightUpDownVector':'\u294F','RightUpTeeVector':'\u295C','RightUpVector':'\u21BE','RightUpVectorBar':'\u2954','RightVector':'\u21C0','RightVectorBar':'\u2953','ring':'\u02DA','risingdotseq':'\u2253','rlarr':'\u21C4','rlhar':'\u21CC','rlm':'\u200F','rmoust':'\u23B1','rmoustache':'\u23B1','rnmid':'\u2AEE','roang':'\u27ED','roarr':'\u21FE','robrk':'\u27E7','ropar':'\u2986','ropf':'\uD835\uDD63','Ropf':'\u211D','roplus':'\u2A2E','rotimes':'\u2A35','RoundImplies':'\u2970','rpar':')','rpargt':'\u2994','rppolint':'\u2A12','rrarr':'\u21C9','Rrightarrow':'\u21DB','rsaquo':'\u203A','rscr':'\uD835\uDCC7','Rscr':'\u211B','rsh':'\u21B1','Rsh':'\u21B1','rsqb':']','rsquo':'\u2019','rsquor':'\u2019','rthree':'\u22CC','rtimes':'\u22CA','rtri':'\u25B9','rtrie':'\u22B5','rtrif':'\u25B8','rtriltri':'\u29CE','RuleDelayed':'\u29F4','ruluhar':'\u2968','rx':'\u211E','sacute':'\u015B','Sacute':'\u015A','sbquo':'\u201A','sc':'\u227B','Sc':'\u2ABC','scap':'\u2AB8','scaron':'\u0161','Scaron':'\u0160','sccue':'\u227D','sce':'\u2AB0','scE':'\u2AB4','scedil':'\u015F','Scedil':'\u015E','scirc':'\u015D','Scirc':'\u015C','scnap':'\u2ABA','scnE':'\u2AB6','scnsim':'\u22E9','scpolint':'\u2A13','scsim':'\u227F','scy':'\u0441','Scy':'\u0421','sdot':'\u22C5','sdotb':'\u22A1','sdote':'\u2A66','searhk':'\u2925','searr':'\u2198','seArr':'\u21D8','searrow':'\u2198','sect':'\xA7','semi':';','seswar':'\u2929','setminus':'\u2216','setmn':'\u2216','sext':'\u2736','sfr':'\uD835\uDD30','Sfr':'\uD835\uDD16','sfrown':'\u2322','sharp':'\u266F','shchcy':'\u0449','SHCHcy':'\u0429','shcy':'\u0448','SHcy':'\u0428','ShortDownArrow':'\u2193','ShortLeftArrow':'\u2190','shortmid':'\u2223','shortparallel':'\u2225','ShortRightArrow':'\u2192','ShortUpArrow':'\u2191','shy':'\xAD','sigma':'\u03C3','Sigma':'\u03A3','sigmaf':'\u03C2','sigmav':'\u03C2','sim':'\u223C','simdot':'\u2A6A','sime':'\u2243','simeq':'\u2243','simg':'\u2A9E','simgE':'\u2AA0','siml':'\u2A9D','simlE':'\u2A9F','simne':'\u2246','simplus':'\u2A24','simrarr':'\u2972','slarr':'\u2190','SmallCircle':'\u2218','smallsetminus':'\u2216','smashp':'\u2A33','smeparsl':'\u29E4','smid':'\u2223','smile':'\u2323','smt':'\u2AAA','smte':'\u2AAC','smtes':'\u2AAC\uFE00','softcy':'\u044C','SOFTcy':'\u042C','sol':'/','solb':'\u29C4','solbar':'\u233F','sopf':'\uD835\uDD64','Sopf':'\uD835\uDD4A','spades':'\u2660','spadesuit':'\u2660','spar':'\u2225','sqcap':'\u2293','sqcaps':'\u2293\uFE00','sqcup':'\u2294','sqcups':'\u2294\uFE00','Sqrt':'\u221A','sqsub':'\u228F','sqsube':'\u2291','sqsubset':'\u228F','sqsubseteq':'\u2291','sqsup':'\u2290','sqsupe':'\u2292','sqsupset':'\u2290','sqsupseteq':'\u2292','squ':'\u25A1','square':'\u25A1','Square':'\u25A1','SquareIntersection':'\u2293','SquareSubset':'\u228F','SquareSubsetEqual':'\u2291','SquareSuperset':'\u2290','SquareSupersetEqual':'\u2292','SquareUnion':'\u2294','squarf':'\u25AA','squf':'\u25AA','srarr':'\u2192','sscr':'\uD835\uDCC8','Sscr':'\uD835\uDCAE','ssetmn':'\u2216','ssmile':'\u2323','sstarf':'\u22C6','star':'\u2606','Star':'\u22C6','starf':'\u2605','straightepsilon':'\u03F5','straightphi':'\u03D5','strns':'\xAF','sub':'\u2282','Sub':'\u22D0','subdot':'\u2ABD','sube':'\u2286','subE':'\u2AC5','subedot':'\u2AC3','submult':'\u2AC1','subne':'\u228A','subnE':'\u2ACB','subplus':'\u2ABF','subrarr':'\u2979','subset':'\u2282','Subset':'\u22D0','subseteq':'\u2286','subseteqq':'\u2AC5','SubsetEqual':'\u2286','subsetneq':'\u228A','subsetneqq':'\u2ACB','subsim':'\u2AC7','subsub':'\u2AD5','subsup':'\u2AD3','succ':'\u227B','succapprox':'\u2AB8','succcurlyeq':'\u227D','Succeeds':'\u227B','SucceedsEqual':'\u2AB0','SucceedsSlantEqual':'\u227D','SucceedsTilde':'\u227F','succeq':'\u2AB0','succnapprox':'\u2ABA','succneqq':'\u2AB6','succnsim':'\u22E9','succsim':'\u227F','SuchThat':'\u220B','sum':'\u2211','Sum':'\u2211','sung':'\u266A','sup':'\u2283','Sup':'\u22D1','sup1':'\xB9','sup2':'\xB2','sup3':'\xB3','supdot':'\u2ABE','supdsub':'\u2AD8','supe':'\u2287','supE':'\u2AC6','supedot':'\u2AC4','Superset':'\u2283','SupersetEqual':'\u2287','suphsol':'\u27C9','suphsub':'\u2AD7','suplarr':'\u297B','supmult':'\u2AC2','supne':'\u228B','supnE':'\u2ACC','supplus':'\u2AC0','supset':'\u2283','Supset':'\u22D1','supseteq':'\u2287','supseteqq':'\u2AC6','supsetneq':'\u228B','supsetneqq':'\u2ACC','supsim':'\u2AC8','supsub':'\u2AD4','supsup':'\u2AD6','swarhk':'\u2926','swarr':'\u2199','swArr':'\u21D9','swarrow':'\u2199','swnwar':'\u292A','szlig':'\xDF','Tab':'\t','target':'\u2316','tau':'\u03C4','Tau':'\u03A4','tbrk':'\u23B4','tcaron':'\u0165','Tcaron':'\u0164','tcedil':'\u0163','Tcedil':'\u0162','tcy':'\u0442','Tcy':'\u0422','tdot':'\u20DB','telrec':'\u2315','tfr':'\uD835\uDD31','Tfr':'\uD835\uDD17','there4':'\u2234','therefore':'\u2234','Therefore':'\u2234','theta':'\u03B8','Theta':'\u0398','thetasym':'\u03D1','thetav':'\u03D1','thickapprox':'\u2248','thicksim':'\u223C','ThickSpace':'\u205F\u200A','thinsp':'\u2009','ThinSpace':'\u2009','thkap':'\u2248','thksim':'\u223C','thorn':'\xFE','THORN':'\xDE','tilde':'\u02DC','Tilde':'\u223C','TildeEqual':'\u2243','TildeFullEqual':'\u2245','TildeTilde':'\u2248','times':'\xD7','timesb':'\u22A0','timesbar':'\u2A31','timesd':'\u2A30','tint':'\u222D','toea':'\u2928','top':'\u22A4','topbot':'\u2336','topcir':'\u2AF1','topf':'\uD835\uDD65','Topf':'\uD835\uDD4B','topfork':'\u2ADA','tosa':'\u2929','tprime':'\u2034','trade':'\u2122','TRADE':'\u2122','triangle':'\u25B5','triangledown':'\u25BF','triangleleft':'\u25C3','trianglelefteq':'\u22B4','triangleq':'\u225C','triangleright':'\u25B9','trianglerighteq':'\u22B5','tridot':'\u25EC','trie':'\u225C','triminus':'\u2A3A','TripleDot':'\u20DB','triplus':'\u2A39','trisb':'\u29CD','tritime':'\u2A3B','trpezium':'\u23E2','tscr':'\uD835\uDCC9','Tscr':'\uD835\uDCAF','tscy':'\u0446','TScy':'\u0426','tshcy':'\u045B','TSHcy':'\u040B','tstrok':'\u0167','Tstrok':'\u0166','twixt':'\u226C','twoheadleftarrow':'\u219E','twoheadrightarrow':'\u21A0','uacute':'\xFA','Uacute':'\xDA','uarr':'\u2191','uArr':'\u21D1','Uarr':'\u219F','Uarrocir':'\u2949','ubrcy':'\u045E','Ubrcy':'\u040E','ubreve':'\u016D','Ubreve':'\u016C','ucirc':'\xFB','Ucirc':'\xDB','ucy':'\u0443','Ucy':'\u0423','udarr':'\u21C5','udblac':'\u0171','Udblac':'\u0170','udhar':'\u296E','ufisht':'\u297E','ufr':'\uD835\uDD32','Ufr':'\uD835\uDD18','ugrave':'\xF9','Ugrave':'\xD9','uHar':'\u2963','uharl':'\u21BF','uharr':'\u21BE','uhblk':'\u2580','ulcorn':'\u231C','ulcorner':'\u231C','ulcrop':'\u230F','ultri':'\u25F8','umacr':'\u016B','Umacr':'\u016A','uml':'\xA8','UnderBar':'_','UnderBrace':'\u23DF','UnderBracket':'\u23B5','UnderParenthesis':'\u23DD','Union':'\u22C3','UnionPlus':'\u228E','uogon':'\u0173','Uogon':'\u0172','uopf':'\uD835\uDD66','Uopf':'\uD835\uDD4C','uparrow':'\u2191','Uparrow':'\u21D1','UpArrow':'\u2191','UpArrowBar':'\u2912','UpArrowDownArrow':'\u21C5','updownarrow':'\u2195','Updownarrow':'\u21D5','UpDownArrow':'\u2195','UpEquilibrium':'\u296E','upharpoonleft':'\u21BF','upharpoonright':'\u21BE','uplus':'\u228E','UpperLeftArrow':'\u2196','UpperRightArrow':'\u2197','upsi':'\u03C5','Upsi':'\u03D2','upsih':'\u03D2','upsilon':'\u03C5','Upsilon':'\u03A5','UpTee':'\u22A5','UpTeeArrow':'\u21A5','upuparrows':'\u21C8','urcorn':'\u231D','urcorner':'\u231D','urcrop':'\u230E','uring':'\u016F','Uring':'\u016E','urtri':'\u25F9','uscr':'\uD835\uDCCA','Uscr':'\uD835\uDCB0','utdot':'\u22F0','utilde':'\u0169','Utilde':'\u0168','utri':'\u25B5','utrif':'\u25B4','uuarr':'\u21C8','uuml':'\xFC','Uuml':'\xDC','uwangle':'\u29A7','vangrt':'\u299C','varepsilon':'\u03F5','varkappa':'\u03F0','varnothing':'\u2205','varphi':'\u03D5','varpi':'\u03D6','varpropto':'\u221D','varr':'\u2195','vArr':'\u21D5','varrho':'\u03F1','varsigma':'\u03C2','varsubsetneq':'\u228A\uFE00','varsubsetneqq':'\u2ACB\uFE00','varsupsetneq':'\u228B\uFE00','varsupsetneqq':'\u2ACC\uFE00','vartheta':'\u03D1','vartriangleleft':'\u22B2','vartriangleright':'\u22B3','vBar':'\u2AE8','Vbar':'\u2AEB','vBarv':'\u2AE9','vcy':'\u0432','Vcy':'\u0412','vdash':'\u22A2','vDash':'\u22A8','Vdash':'\u22A9','VDash':'\u22AB','Vdashl':'\u2AE6','vee':'\u2228','Vee':'\u22C1','veebar':'\u22BB','veeeq':'\u225A','vellip':'\u22EE','verbar':'|','Verbar':'\u2016','vert':'|','Vert':'\u2016','VerticalBar':'\u2223','VerticalLine':'|','VerticalSeparator':'\u2758','VerticalTilde':'\u2240','VeryThinSpace':'\u200A','vfr':'\uD835\uDD33','Vfr':'\uD835\uDD19','vltri':'\u22B2','vnsub':'\u2282\u20D2','vnsup':'\u2283\u20D2','vopf':'\uD835\uDD67','Vopf':'\uD835\uDD4D','vprop':'\u221D','vrtri':'\u22B3','vscr':'\uD835\uDCCB','Vscr':'\uD835\uDCB1','vsubne':'\u228A\uFE00','vsubnE':'\u2ACB\uFE00','vsupne':'\u228B\uFE00','vsupnE':'\u2ACC\uFE00','Vvdash':'\u22AA','vzigzag':'\u299A','wcirc':'\u0175','Wcirc':'\u0174','wedbar':'\u2A5F','wedge':'\u2227','Wedge':'\u22C0','wedgeq':'\u2259','weierp':'\u2118','wfr':'\uD835\uDD34','Wfr':'\uD835\uDD1A','wopf':'\uD835\uDD68','Wopf':'\uD835\uDD4E','wp':'\u2118','wr':'\u2240','wreath':'\u2240','wscr':'\uD835\uDCCC','Wscr':'\uD835\uDCB2','xcap':'\u22C2','xcirc':'\u25EF','xcup':'\u22C3','xdtri':'\u25BD','xfr':'\uD835\uDD35','Xfr':'\uD835\uDD1B','xharr':'\u27F7','xhArr':'\u27FA','xi':'\u03BE','Xi':'\u039E','xlarr':'\u27F5','xlArr':'\u27F8','xmap':'\u27FC','xnis':'\u22FB','xodot':'\u2A00','xopf':'\uD835\uDD69','Xopf':'\uD835\uDD4F','xoplus':'\u2A01','xotime':'\u2A02','xrarr':'\u27F6','xrArr':'\u27F9','xscr':'\uD835\uDCCD','Xscr':'\uD835\uDCB3','xsqcup':'\u2A06','xuplus':'\u2A04','xutri':'\u25B3','xvee':'\u22C1','xwedge':'\u22C0','yacute':'\xFD','Yacute':'\xDD','yacy':'\u044F','YAcy':'\u042F','ycirc':'\u0177','Ycirc':'\u0176','ycy':'\u044B','Ycy':'\u042B','yen':'\xA5','yfr':'\uD835\uDD36','Yfr':'\uD835\uDD1C','yicy':'\u0457','YIcy':'\u0407','yopf':'\uD835\uDD6A','Yopf':'\uD835\uDD50','yscr':'\uD835\uDCCE','Yscr':'\uD835\uDCB4','yucy':'\u044E','YUcy':'\u042E','yuml':'\xFF','Yuml':'\u0178','zacute':'\u017A','Zacute':'\u0179','zcaron':'\u017E','Zcaron':'\u017D','zcy':'\u0437','Zcy':'\u0417','zdot':'\u017C','Zdot':'\u017B','zeetrf':'\u2128','ZeroWidthSpace':'\u200B','zeta':'\u03B6','Zeta':'\u0396','zfr':'\uD835\uDD37','Zfr':'\u2128','zhcy':'\u0436','ZHcy':'\u0416','zigrarr':'\u21DD','zopf':'\uD835\uDD6B','Zopf':'\u2124','zscr':'\uD835\uDCCF','Zscr':'\uD835\uDCB5','zwj':'\u200D','zwnj':'\u200C'};
+ var decodeMapLegacy = {'aacute':'\xE1','Aacute':'\xC1','acirc':'\xE2','Acirc':'\xC2','acute':'\xB4','aelig':'\xE6','AElig':'\xC6','agrave':'\xE0','Agrave':'\xC0','amp':'&','AMP':'&','aring':'\xE5','Aring':'\xC5','atilde':'\xE3','Atilde':'\xC3','auml':'\xE4','Auml':'\xC4','brvbar':'\xA6','ccedil':'\xE7','Ccedil':'\xC7','cedil':'\xB8','cent':'\xA2','copy':'\xA9','COPY':'\xA9','curren':'\xA4','deg':'\xB0','divide':'\xF7','eacute':'\xE9','Eacute':'\xC9','ecirc':'\xEA','Ecirc':'\xCA','egrave':'\xE8','Egrave':'\xC8','eth':'\xF0','ETH':'\xD0','euml':'\xEB','Euml':'\xCB','frac12':'\xBD','frac14':'\xBC','frac34':'\xBE','gt':'>','GT':'>','iacute':'\xED','Iacute':'\xCD','icirc':'\xEE','Icirc':'\xCE','iexcl':'\xA1','igrave':'\xEC','Igrave':'\xCC','iquest':'\xBF','iuml':'\xEF','Iuml':'\xCF','laquo':'\xAB','lt':'<','LT':'<','macr':'\xAF','micro':'\xB5','middot':'\xB7','nbsp':'\xA0','not':'\xAC','ntilde':'\xF1','Ntilde':'\xD1','oacute':'\xF3','Oacute':'\xD3','ocirc':'\xF4','Ocirc':'\xD4','ograve':'\xF2','Ograve':'\xD2','ordf':'\xAA','ordm':'\xBA','oslash':'\xF8','Oslash':'\xD8','otilde':'\xF5','Otilde':'\xD5','ouml':'\xF6','Ouml':'\xD6','para':'\xB6','plusmn':'\xB1','pound':'\xA3','quot':'"','QUOT':'"','raquo':'\xBB','reg':'\xAE','REG':'\xAE','sect':'\xA7','shy':'\xAD','sup1':'\xB9','sup2':'\xB2','sup3':'\xB3','szlig':'\xDF','thorn':'\xFE','THORN':'\xDE','times':'\xD7','uacute':'\xFA','Uacute':'\xDA','ucirc':'\xFB','Ucirc':'\xDB','ugrave':'\xF9','Ugrave':'\xD9','uml':'\xA8','uuml':'\xFC','Uuml':'\xDC','yacute':'\xFD','Yacute':'\xDD','yen':'\xA5','yuml':'\xFF'};
+ var decodeMapNumeric = {'0':'\uFFFD','128':'\u20AC','130':'\u201A','131':'\u0192','132':'\u201E','133':'\u2026','134':'\u2020','135':'\u2021','136':'\u02C6','137':'\u2030','138':'\u0160','139':'\u2039','140':'\u0152','142':'\u017D','145':'\u2018','146':'\u2019','147':'\u201C','148':'\u201D','149':'\u2022','150':'\u2013','151':'\u2014','152':'\u02DC','153':'\u2122','154':'\u0161','155':'\u203A','156':'\u0153','158':'\u017E','159':'\u0178'};
+ var invalidReferenceCodePoints = [1,2,3,4,5,6,7,8,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,64976,64977,64978,64979,64980,64981,64982,64983,64984,64985,64986,64987,64988,64989,64990,64991,64992,64993,64994,64995,64996,64997,64998,64999,65000,65001,65002,65003,65004,65005,65006,65007,65534,65535,131070,131071,196606,196607,262142,262143,327678,327679,393214,393215,458750,458751,524286,524287,589822,589823,655358,655359,720894,720895,786430,786431,851966,851967,917502,917503,983038,983039,1048574,1048575,1114110,1114111];
+
+ /*--------------------------------------------------------------------------*/
+
+ var stringFromCharCode = String.fromCharCode;
+
+ var object = {};
+ var hasOwnProperty = object.hasOwnProperty;
+ var has = function(object, propertyName) {
+ return hasOwnProperty.call(object, propertyName);
+ };
+
+ var contains = function(array, value) {
+ var index = -1;
+ var _length = array.length;
+ while (++index < _length) {
+ if (array[index] == value) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ var merge = function(options, defaults) {
+ if (!options) {
+ return defaults;
+ }
+ var result = {};
+ var key;
+ for (key in defaults) {
+ // A `hasOwnProperty` check is not needed here, since only recognized
+ // option names are used anyway. Any others are ignored.
+ result[key] = has(options, key) ? options[key] : defaults[key];
+ }
+ return result;
+ };
+
+ // Modified version of `ucs2encode`; see https://mths.be/punycode.
+ var codePointToSymbol = function(codePoint, strict) {
+ var output = '';
+ if ((codePoint >= 0xD800 && codePoint <= 0xDFFF) || codePoint > 0x10FFFF) {
+ // See issue #4:
+ // “Otherwise, if the number is in the range 0xD800 to 0xDFFF or is
+ // greater than 0x10FFFF, then this is a parse error. Return a U+FFFD
+ // REPLACEMENT CHARACTER.”
+ if (strict) {
+ parseError('character reference outside the permissible Unicode range');
+ }
+ return '\uFFFD';
+ }
+ if (has(decodeMapNumeric, codePoint)) {
+ if (strict) {
+ parseError('disallowed character reference');
+ }
+ return decodeMapNumeric[codePoint];
+ }
+ if (strict && contains(invalidReferenceCodePoints, codePoint)) {
+ parseError('disallowed character reference');
+ }
+ if (codePoint > 0xFFFF) {
+ codePoint -= 0x10000;
+ output += stringFromCharCode(codePoint >>> 10 & 0x3FF | 0xD800);
+ codePoint = 0xDC00 | codePoint & 0x3FF;
+ }
+ output += stringFromCharCode(codePoint);
+ return output;
+ };
+
+ var hexEscape = function(codePoint) {
+ return '' + codePoint.toString(16).toUpperCase() + ';';
+ };
+
+ var decEscape = function(codePoint) {
+ return '' + codePoint + ';';
+ };
+
+ var parseError = function(message) {
+ throw Error('Parse error: ' + message);
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ var encode = function(string, options) {
+ options = merge(options, encode.options);
+ var strict = options.strict;
+ if (strict && regexInvalidRawCodePoint.test(string)) {
+ parseError('forbidden code point');
+ }
+ var encodeEverything = options.encodeEverything;
+ var useNamedReferences = options.useNamedReferences;
+ var allowUnsafeSymbols = options.allowUnsafeSymbols;
+ var escapeCodePoint = options.decimal ? decEscape : hexEscape;
+
+ var escapeBmpSymbol = function(symbol) {
+ return escapeCodePoint(symbol.charCodeAt(0));
+ };
+
+ if (encodeEverything) {
+ // Encode ASCII symbols.
+ string = string.replace(regexAsciiWhitelist, function(symbol) {
+ // Use named references if requested & possible.
+ if (useNamedReferences && has(encodeMap, symbol)) {
+ return '&' + encodeMap[symbol] + ';';
+ }
+ return escapeBmpSymbol(symbol);
+ });
+ // Shorten a few escapes that represent two symbols, of which at least one
+ // is within the ASCII range.
+ if (useNamedReferences) {
+ string = string
+ .replace(/>\u20D2/g, '>⃒')
+ .replace(/<\u20D2/g, '<⃒')
+ .replace(/fj/g, 'fj');
+ }
+ // Encode non-ASCII symbols.
+ if (useNamedReferences) {
+ // Encode non-ASCII symbols that can be replaced with a named reference.
+ string = string.replace(regexEncodeNonAscii, function(string) {
+ // Note: there is no need to check `has(encodeMap, string)` here.
+ return '&' + encodeMap[string] + ';';
+ });
+ }
+ // Note: any remaining non-ASCII symbols are handled outside of the `if`.
+ } else if (useNamedReferences) {
+ // Apply named character references.
+ // Encode `<>"'&` using named character references.
+ if (!allowUnsafeSymbols) {
+ string = string.replace(regexEscape, function(string) {
+ return '&' + encodeMap[string] + ';'; // no need to check `has()` here
+ });
+ }
+ // Shorten escapes that represent two symbols, of which at least one is
+ // `<>"'&`.
+ string = string
+ .replace(/>\u20D2/g, '>⃒')
+ .replace(/<\u20D2/g, '<⃒');
+ // Encode non-ASCII symbols that can be replaced with a named reference.
+ string = string.replace(regexEncodeNonAscii, function(string) {
+ // Note: there is no need to check `has(encodeMap, string)` here.
+ return '&' + encodeMap[string] + ';';
+ });
+ } else if (!allowUnsafeSymbols) {
+ // Encode `<>"'&` using hexadecimal escapes, now that they’re not handled
+ // using named character references.
+ string = string.replace(regexEscape, escapeBmpSymbol);
+ }
+ return string
+ // Encode astral symbols.
+ .replace(regexAstralSymbols, function($0) {
+ // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+ var high = $0.charCodeAt(0);
+ var low = $0.charCodeAt(1);
+ var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
+ return escapeCodePoint(codePoint);
+ })
+ // Encode any remaining BMP symbols that are not printable ASCII symbols
+ // using a hexadecimal escape.
+ .replace(regexBmpWhitelist, escapeBmpSymbol);
+ };
+ // Expose default options (so they can be overridden globally).
+ encode.options = {
+ 'allowUnsafeSymbols': false,
+ 'encodeEverything': false,
+ 'strict': false,
+ 'useNamedReferences': false,
+ 'decimal' : false
+ };
+
+ var decode = function(html, options) {
+ options = merge(options, decode.options);
+ var strict = options.strict;
+ if (strict && regexInvalidEntity.test(html)) {
+ parseError('malformed character reference');
+ }
+ return html.replace(regexDecode, function($0, $1, $2, $3, $4, $5, $6, $7, $8) {
+ var codePoint;
+ var semicolon;
+ var decDigits;
+ var hexDigits;
+ var reference;
+ var next;
+
+ if ($1) {
+ reference = $1;
+ // Note: there is no need to check `has(decodeMap, reference)`.
+ return decodeMap[reference];
+ }
+
+ if ($2) {
+ // Decode named character references without trailing `;`, e.g. `&`.
+ // This is only a parse error if it gets converted to `&`, or if it is
+ // followed by `=` in an attribute context.
+ reference = $2;
+ next = $3;
+ if (next && options.isAttributeValue) {
+ if (strict && next == '=') {
+ parseError('`&` did not start a character reference');
+ }
+ return $0;
+ } else {
+ if (strict) {
+ parseError(
+ 'named character reference was not terminated by a semicolon'
+ );
+ }
+ // Note: there is no need to check `has(decodeMapLegacy, reference)`.
+ return decodeMapLegacy[reference] + (next || '');
+ }
+ }
+
+ if ($4) {
+ // Decode decimal escapes, e.g. `𝌆`.
+ decDigits = $4;
+ semicolon = $5;
+ if (strict && !semicolon) {
+ parseError('character reference was not terminated by a semicolon');
+ }
+ codePoint = parseInt(decDigits, 10);
+ return codePointToSymbol(codePoint, strict);
+ }
+
+ if ($6) {
+ // Decode hexadecimal escapes, e.g. `𝌆`.
+ hexDigits = $6;
+ semicolon = $7;
+ if (strict && !semicolon) {
+ parseError('character reference was not terminated by a semicolon');
+ }
+ codePoint = parseInt(hexDigits, 16);
+ return codePointToSymbol(codePoint, strict);
+ }
+
+ // If we’re still here, `if ($7)` is implied; it’s an ambiguous
+ // ampersand for sure. https://mths.be/notes/ambiguous-ampersands
+ if (strict) {
+ parseError(
+ 'named character reference was not terminated by a semicolon'
+ );
+ }
+ return $0;
+ });
+ };
+ // Expose default options (so they can be overridden globally).
+ decode.options = {
+ 'isAttributeValue': false,
+ 'strict': false
+ };
+
+ var escape = function(string) {
+ return string.replace(regexEscape, function($0) {
+ // Note: there is no need to check `has(escapeMap, $0)` here.
+ return escapeMap[$0];
+ });
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ var he = {
+ 'version': '1.2.0',
+ 'encode': encode,
+ 'decode': decode,
+ 'escape': escape,
+ 'unescape': decode
+ };
+
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof define == 'function' &&
+ typeof define.amd == 'object' &&
+ define.amd
+ ) {
+ define(function() {
+ return he;
+ });
+ } else if (freeExports && !freeExports.nodeType) {
+ if (freeModule) { // in Node.js, io.js, or RingoJS v0.8.0+
+ freeModule.exports = he;
+ } else { // in Narwhal or RingoJS v0.7.0-
+ for (var key in he) {
+ has(he, key) && (freeExports[key] = he[key]);
+ }
+ }
+ } else { // in Rhino or a web browser
+ root.he = he;
+ }
+
+}(this));
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/lib/xml2json.min.js b/sound150@claudiux/files/sound150@claudiux/6.4/lib/xml2json.min.js
new file mode 100644
index 00000000000..6b6ee834015
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/lib/xml2json.min.js
@@ -0,0 +1 @@
+"use strict";function xml2json(e){return e=cleanXML(e),xml2jsonRecurse(e,0)}function xml2jsonRecurse(e){for(var r,t,n,a,s,l={};e.match(/<[^\/][^>]*>/);)s=e.match(/<[^\/][^>]*>/)[0],r=s.substring(1,s.length-1),t=e.indexOf(s.replace("<","")),-1==t&&(r=s.match(/[^<][\w+$]*/)[0],t=e.indexOf(""+r),-1==t&&(t=e.indexOf("<\\/"+r))),n=e.substring(s.length,t),a=n.match(/<[^\/][^>]*>/)?xml2json(n):n,void 0===l[r]?l[r]=a:Array.isArray(l[r])?l[r].push(a):l[r]=[l[r],a],e=e.substring(2*s.length+1+n.length);return l}function cleanXML(e){return e=e.replace(//g,""),e=e.replace(/\n|\t|\r/g,""),e=e.replace(/ {1,}<|\t{1,} {1,}|>\t{1,}/g,">"),e=e.replace(/<\?[^>]*\?>/g,""),e=replaceSelfClosingTags(e),e=replaceAloneValues(e),e=replaceAttributes(e)}function replaceSelfClosingTags(e){var r=e.match(/<[^\/][^>]*\/>/g);if(r)for(var t=0;t";var s=n.match(/[^<][\w+$]*/)[0],l=""+s+">",i="<"+s+">",c=a.match(/(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/g);if(c)for(var g=0;g"+o+""+f+">"}i+=l,e=e.replace(n,i)}return e}function replaceAloneValues(e){var r=e.match(/<[^\/][^>][^<]+\s+.[^<]+[=][^<]+>{1}([^<]+)/g);if(r)for(var t=0;t")+1),s=n.substring(n.indexOf(">")+1),l=a+"<_@ttribute>"+s+"";e=e.replace(n,l)}return e}function replaceAttributes(e){var r=e.match(/<[^\/][^>][^<]+\s+.[^<]+[=][^<]+>/g);if(r)for(var t=0;t",l=n.match(/(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/g);if(l)for(var i=0;i"+u+""+g+">"}e=e.replace(n,s)}return e}module.exports={xml2json:xml2json};
diff --git a/sound150@claudiux/files/sound150@claudiux/6.4/settings-schema.json b/sound150@claudiux/files/sound150@claudiux/6.4/settings-schema.json
new file mode 100644
index 00000000000..ed86cd2199e
--- /dev/null
+++ b/sound150@claudiux/files/sound150@claudiux/6.4/settings-schema.json
@@ -0,0 +1,460 @@
+{
+ "layoutsound150": {
+ "type": "layout",
+ "pages": [
+ "page_behavior",
+ "page_sound",
+ "page_icon",
+ "page_shortcuts"
+ ],
+ "page_behavior": {
+ "type": "page",
+ "title": "Behavior",
+ "sections": [
+ "sectionBehavior1",
+ "sectionBehavior2",
+ "sectionBehavior3"
+ ]
+ },
+ "page_icon": {
+ "type": "page",
+ "title": "Icon",
+ "sections": [
+ "sectionIcon1"
+ ]
+ },
+ "page_sound": {
+ "type": "page",
+ "title": "Sound",
+ "sections": [
+ "sectionSound1",
+ "sectionSound2",
+ "sectionSound3",
+ "sectionSound4"
+ ]
+ },
+ "page_shortcuts": {
+ "type": "page",
+ "title": "Shortcuts",
+ "sections": [
+ "sectionShortcuts1"
+ ]
+ },
+ "sectionBehavior1": {
+ "type": "section",
+ "title": "Menu",
+ "keys": [
+ "playerControl",
+ "extendedPlayerControl",
+ "keepPlayerListOpen",
+ "keepChoosePlayerOpen",
+ "avoidTwice",
+ "seekerTooltipDelay"
+ ]
+ },
+ "sectionBehavior2": {
+ "type": "section",
+ "title": "Panel",
+ "keys": [
+ "showtrack",
+ "truncatetext",
+ "middleClickAction",
+ "middleShiftClickAction",
+ "horizontalScroll",
+ "showalbum",
+ "keepAlbumAspectRatio",
+ "hideSystray"
+ ]
+ },
+ "sectionBehavior3": {
+ "type": "section",
+ "title": "Tooltip",
+ "keys": [
+ "tooltipShowVolume",
+ "tooltipShowPlayer",
+ "tooltipShowArtistTitle"
+ ]
+ },
+ "sectionIcon1": {
+ "type": "section",
+ "title": "Icon",
+ "keys": [
+ "showalbum",
+ "keepAlbumAspectRatio",
+ "showVolumeLevelNearIcon",
+ "showMicMutedOnIcon",
+ "showMicUnmutedOnIcon",
+ "adaptColor",
+ "color101_115",
+ "color116_130",
+ "color131_150",
+ "resetColorsButton"
+ ]
+ },
+ "sectionSound1": {
+ "type": "section",
+ "title": "Sound Settings",
+ "keys": [
+ "setAmplification",
+ "stepVolume",
+ "magneticOn",
+ "magnetic25On",
+ "alwaysCanChangeMic"
+ ]
+ },
+ "sectionSound2": {
+ "type": "section",
+ "title": "OSD",
+ "keys": [
+ "showMediaKeysOSD",
+ "showOSDonStartup"
+ ]
+ },
+ "sectionSound3": {
+ "type": "section",
+ "title": "Sounds",
+ "keys": [
+ "volumeSoundFile",
+ "volumeSoundEnabled"
+ ]
+ },
+ "sectionSound4": {
+ "type": "section",
+ "dependency": "soundATcinnamonDOTorg_is_loaded",
+ "title": "Remove incompatible applets",
+ "keys": [
+ "remove_soundATcinnamonDOTorg"
+ ]
+ },
+ "sectionShortcuts1": {
+ "type": "section",
+ "title": "Shortcuts",
+ "keys": [
+ "keyOpen",
+ "keySwitchPlayer",
+ "redefine-volume-keybindings",
+ "button-set-to-default-keybindings",
+ "audio-stop",
+ "pause-on-off",
+ "volume-mute",
+ "volume-up",
+ "volume-down",
+ "audio-next",
+ "audio-prev"
+ ]
+ }
+ },
+ "playerControl": {
+ "type": "switch",
+ "default": true,
+ "description": "Control Players"
+ },
+ "extendedPlayerControl": {
+ "type": "switch",
+ "default": false,
+ "description": "Show Loop and Shuffle controls",
+ "dependency": "playerControl"
+ },
+ "keepPlayerListOpen": {
+ "type": "switch",
+ "dependency": "playerControl",
+ "default": false,
+ "description": "Keep the player list open"
+ },
+ "keepChoosePlayerOpen": {
+ "type": "switch",
+ "default": false,
+ "description": "Keep the player controller selector open"
+ },
+ "avoidTwice": {
+ "type": "switch",
+ "default": false,
+ "description": "Avoid displaying controllers twice"
+ },
+ "seekerTooltipDelay": {
+ "type": "spinbutton",
+ "default": 400,
+ "units": "ms",
+ "min": 50,
+ "max": 1500,
+ "step": 50,
+ "description": "Seeker tooltip: time to disappear"
+ },
+ "keyOpen": {
+ "type": "keybinding",
+ "description": "Show menu",
+ "default": "s",
+ "tooltip": "Set keybinding(s) to show the sound applet menu."
+ },
+ "keySwitchPlayer": {
+ "type": "keybinding",
+ "description": "Switch to next player",
+ "default": "::",
+ "tooltip": "Set keybinding(s) to switch to the next player if it exists."
+ },
+ "_knownPlayers": {
+ "type": "generic",
+ "default": [
+ "banshee",
+ "vlc",
+ "rhythmbox"
+ ]
+ },
+ "showtrack": {
+ "type": "switch",
+ "default": false,
+ "description": "Show song information on the panel",
+ "dependency": "playerControl"
+ },
+ "truncatetext": {
+ "type": "spinbutton",
+ "default": 30,
+ "min": 5,
+ "max": 512,
+ "units": "characters",
+ "step": 1,
+ "description": "Limit song information to",
+ "dependency": "showtrack"
+ },
+ "middleClickAction": {
+ "type": "combobox",
+ "default": "out_mute",
+ "options": {
+ "Toggle Mute": "mute",
+ "Toggle Mute output": "out_mute",
+ "Toggle Mute input": "in_mute",
+ "Toggle Play / Pause": "player"
+ },
+ "description": "Action on middle click"
+ },
+ "middleShiftClickAction": {
+ "type": "combobox",
+ "default": "in_mute",
+ "options": {
+ "Toggle Mute": "mute",
+ "Toggle Mute output": "out_mute",
+ "Toggle Mute input": "in_mute",
+ "Toggle Play / Pause": "player"
+ },
+ "description": "Action on shift+middle click"
+ },
+ "horizontalScroll": {
+ "type": "switch",
+ "default": false,
+ "description": "Use horizontal scrolling to move between tracks",
+ "dependency": "playerControl"
+ },
+ "showalbum": {
+ "type": "switch",
+ "default": false,
+ "description": "Show album art as icon",
+ "dependency": "playerControl"
+ },
+ "keepAlbumAspectRatio": {
+ "type": "switch",
+ "default": true,
+ "description": "Keep album art aspect ratio",
+ "dependency": "playerControl"
+ },
+ "hideSystray": {
+ "type": "switch",
+ "description": "Hide system tray icons for compatible players",
+ "default": true
+ },
+ "tooltipShowVolume": {
+ "type": "switch",
+ "default": true,
+ "description": "Show volume in tooltip"
+ },
+ "tooltipShowPlayer": {
+ "type": "switch",
+ "default": false,
+ "description": "Show player in tooltip"
+ },
+ "tooltipShowArtistTitle": {
+ "type": "switch",
+ "default": false,
+ "description": "Show song artist and title in tooltip"
+ },
+ "showVolumeLevelNearIcon": {
+ "type": "switch",
+ "default": false,
+ "description": "Display volume level near icon"
+ },
+ "showMicMutedOnIcon": {
+ "type": "switch",
+ "default": true,
+ "description": "Display icon indicating that the microphone is muted, if applicable"
+ },
+ "showMicUnmutedOnIcon": {
+ "type": "switch",
+ "default": false,
+ "description": "Display icon indicating that the microphone is activated, if applicable"
+ },
+ "setAmplification": {
+ "type": "button",
+ "description": "Maximum volume control",
+ "callback": "_onSetApmlificationPressed"
+ },
+ "stepVolume": {
+ "type": "combobox",
+ "default": 5,
+ "options": {
+ "10%": 10,
+ "9%": 9,
+ "8%": 8,
+ "7%": 7,
+ "6%": 6,
+ "5%": 5,
+ "4%": 4,
+ "3%": 3,
+ "2%": 2,
+ "1%": 1
+ },
+ "tooltip": "% of nominal volume",
+ "description": "+/-"
+ },
+ "magneticOn": {
+ "type": "switch",
+ "description": "Magnetize the 'Volume 100%' mark",
+ "tooltip": "When checked, the 'Volume 100%' mark becomes magnetic: the volume is automatically set to 100% when the distance between the volume value and 100% is lesser than a half-step.",
+ "default": true
+ },
+ "magnetic25On": {
+ "type": "switch",
+ "description": "Magnetize all multiples of 25%",
+ "dependency": "magneticOn",
+ "default": false
+ },
+ "adaptColor": {
+ "type": "switch",
+ "description": "Adjust the color of the icon to the volume",
+ "default": true
+ },
+ "color101_115": {
+ "type": "colorchooser",
+ "dependency": "adaptColor",
+ "default": "yellow",
+ "description": "Icon color: 101%-115%"
+ },
+ "color116_130": {
+ "type": "colorchooser",
+ "dependency": "adaptColor",
+ "default": "orange",
+ "description": "Icon color: 116%-130%"
+ },
+ "color131_150": {
+ "type": "colorchooser",
+ "dependency": "adaptColor",
+ "default": "red",
+ "description": "Icon color: 131%-150%"
+ },
+ "resetColorsButton": {
+ "type": "button",
+ "dependency": "adaptColor",
+ "description": "Set colors to default values (yellow, orange, red)",
+ "callback": "_reset_colors"
+ },
+ "alwaysCanChangeMic": {
+ "type": "switch",
+ "description": "Always allow microphone to be reactivated",
+ "tooltip": "Always show the 'Mute input' switch in the context menu.",
+ "default": true
+ },
+ "showMediaKeysOSD": {
+ "type": "combobox",
+ "default": "medium",
+ "options": {
+ "disabled": "disabled",
+ "small": "small",
+ "medium": "medium",
+ "large": "large"
+ },
+ "description": "Whether the media keys osd is disabled or its relative display size"
+ },
+ "showOSDonStartup": {
+ "type": "switch",
+ "description": "Show volume level in OSD on startup",
+ "default": false
+ },
+ "volumeSoundFile": {
+ "type": "soundfilechooser",
+ "description": "Which sound to play when the volume is changed",
+ "default": "/usr/share/mint-artwork/sounds/volume.oga"
+ },
+ "volumeSoundEnabled": {
+ "type": "switch",
+ "description": "Whether to play a sound when the volume is changed",
+ "default": false
+ },
+ "redefine-volume-keybindings": {
+ "type": "switch",
+ "description": "Redefine Multimedia Keyboard Shortcuts",
+ "default": false
+ },
+ "button-set-to-default-keybindings": {
+ "type": "button",
+ "dependency": "redefine-volume-keybindings",
+ "description": "Use the same shortcuts as those defined by Cinnamon",
+ "callback": "_set_shortcuts_as_default"
+ },
+ "pause-on-off": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Pause/Play toggle"
+ },
+ "audio-stop": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Stop"
+ },
+ "volume-mute": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Volume Mute"
+ },
+ "volume-up": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Volume Up"
+ },
+ "volume-down": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Volume Down"
+ },
+ "audio-next": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Next Track"
+ },
+ "audio-prev": {
+ "type": "keybinding",
+ "dependency": "redefine-volume-keybindings",
+ "default": "::",
+ "description": "Previous Track"
+ },
+ "volume": {
+ "type": "generic",
+ "default": "50%"
+ },
+ "mic-level": {
+ "type": "generic",
+ "default": "50%"
+ },
+ "soundATcinnamonDOTorg_is_loaded": {
+ "type": "generic",
+ "default": false
+ },
+ "remove_soundATcinnamonDOTorg": {
+ "type": "button",
+ "description": "Remove from panel the sound@cinnamon.org applet",
+ "callback": "_on_remove_soundATcinnamonDOTorg_from_panels"
+ }
+}