Merge branch 'master' into tracking
Conflicts: index.html
|
@ -154,8 +154,8 @@ var config = {
|
|||
bridge: 'jitsi-videobridge.jitsi.example.com'
|
||||
},
|
||||
useNicks: false,
|
||||
bosh: '//jitsi.example.com/http-bind' // FIXME: use xep-0156 for that
|
||||
desktopSharing: 'false', // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
|
||||
bosh: '//jitsi.example.com/http-bind', // FIXME: use xep-0156 for that
|
||||
desktopSharing: 'false' // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
|
||||
//chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
|
||||
//minChromeExtVersion: '0.1' // Required version of Chrome extension
|
||||
};
|
||||
|
|
108
app.js
|
@ -70,18 +70,18 @@ function init() {
|
|||
}
|
||||
|
||||
obtainAudioAndVideoPermissions(function (stream) {
|
||||
var audioStream = new webkitMediaStream(stream);
|
||||
var videoStream = new webkitMediaStream(stream);
|
||||
var videoTracks = stream.getVideoTracks();
|
||||
var audioStream = new webkitMediaStream();
|
||||
var videoStream = new webkitMediaStream();
|
||||
var audioTracks = stream.getAudioTracks();
|
||||
for (var i = 0; i < videoTracks.length; i++) {
|
||||
audioStream.removeTrack(videoTracks[i]);
|
||||
var videoTracks = stream.getVideoTracks();
|
||||
for (var i = 0; i < audioTracks.length; i++) {
|
||||
audioStream.addTrack(audioTracks[i]);
|
||||
}
|
||||
VideoLayout.changeLocalAudio(audioStream);
|
||||
startLocalRtpStatsCollector(audioStream);
|
||||
|
||||
for (i = 0; i < audioTracks.length; i++) {
|
||||
videoStream.removeTrack(audioTracks[i]);
|
||||
for (i = 0; i < videoTracks.length; i++) {
|
||||
videoStream.addTrack(videoTracks[i]);
|
||||
}
|
||||
VideoLayout.changeLocalVideo(videoStream, true);
|
||||
maybeDoJoin();
|
||||
|
@ -245,7 +245,9 @@ function waitForRemoteVideo(selector, ssrc, stream) {
|
|||
if (stream.id === 'mixedmslabel') return;
|
||||
|
||||
if (selector[0].currentTime > 0) {
|
||||
RTC.attachMediaStream(selector, stream); // FIXME: why do i have to do this for FF?
|
||||
var simulcast = new Simulcast();
|
||||
var videoStream = simulcast.getReceivingVideoStream(stream);
|
||||
RTC.attachMediaStream(selector, videoStream); // FIXME: why do i have to do this for FF?
|
||||
|
||||
// FIXME: add a class that will associate peer Jid, video.src, it's ssrc and video type
|
||||
// in order to get rid of too many maps
|
||||
|
@ -264,18 +266,40 @@ function waitForRemoteVideo(selector, ssrc, stream) {
|
|||
}
|
||||
|
||||
$(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||
waitForPresence(data, sid);
|
||||
});
|
||||
|
||||
function waitForPresence(data, sid) {
|
||||
var sess = connection.jingle.sessions[sid];
|
||||
|
||||
var thessrc;
|
||||
// look up an associated JID for a stream id
|
||||
if (data.stream.id.indexOf('mixedmslabel') === -1) {
|
||||
// look only at a=ssrc: and _not_ at a=ssrc-group: lines
|
||||
var ssrclines
|
||||
= SDPUtil.find_lines(sess.peerconnection.remoteDescription.sdp, 'a=ssrc');
|
||||
= SDPUtil.find_lines(sess.peerconnection.remoteDescription.sdp, 'a=ssrc:');
|
||||
ssrclines = ssrclines.filter(function (line) {
|
||||
return line.indexOf('mslabel:' + data.stream.label) !== -1;
|
||||
});
|
||||
if (ssrclines.length) {
|
||||
thessrc = ssrclines[0].substring(7).split(' ')[0];
|
||||
|
||||
// We signal our streams (through Jingle to the focus) before we set
|
||||
// our presence (through which peers associate remote streams to
|
||||
// jids). So, it might arrive that a remote stream is added but
|
||||
// ssrc2jid is not yet updated and thus data.peerjid cannot be
|
||||
// successfully set. Here we wait for up to a second for the
|
||||
// presence to arrive.
|
||||
|
||||
if (!ssrc2jid[thessrc]) {
|
||||
setTimeout(function(d, s) {
|
||||
return function() {
|
||||
waitForPresence(d, s);
|
||||
}
|
||||
}(data, sid), 250);
|
||||
return;
|
||||
}
|
||||
|
||||
// ok to overwrite the one from focus? might save work in colibri.js
|
||||
console.log('associated jid', ssrc2jid[thessrc], data.peerjid);
|
||||
if (ssrc2jid[thessrc]) {
|
||||
|
@ -284,6 +308,9 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE(gp) now that we have simulcast, a media stream can have more than 1
|
||||
// ssrc. We should probably take that into account in our MediaStream
|
||||
// wrapper.
|
||||
mediaStreams.push(new MediaStream(data, sid, thessrc));
|
||||
|
||||
var container;
|
||||
|
@ -330,7 +357,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
|||
sendKeyframe(sess.peerconnection);
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JID of the user to whom given <tt>videoSrc</tt> belongs.
|
||||
|
@ -540,40 +567,35 @@ $(document).bind('callterminated.jingle', function (event, sid, jid, reason) {
|
|||
$(document).bind('setLocalDescription.jingle', function (event, sid) {
|
||||
// put our ssrcs into presence so other clients can identify our stream
|
||||
var sess = connection.jingle.sessions[sid];
|
||||
var newssrcs = {};
|
||||
var directions = {};
|
||||
var localSDP = new SDP(sess.peerconnection.localDescription.sdp);
|
||||
localSDP.media.forEach(function (media) {
|
||||
var type = SDPUtil.parse_mid(SDPUtil.find_line(media, 'a=mid:'));
|
||||
var newssrcs = [];
|
||||
var simulcast = new Simulcast();
|
||||
var media = simulcast.parseMedia(sess.peerconnection.localDescription);
|
||||
media.forEach(function (media) {
|
||||
|
||||
if (SDPUtil.find_line(media, 'a=ssrc:')) {
|
||||
// assumes a single local ssrc
|
||||
var ssrc = SDPUtil.find_line(media, 'a=ssrc:').substring(7).split(' ')[0];
|
||||
newssrcs[type] = ssrc;
|
||||
|
||||
directions[type] = (
|
||||
SDPUtil.find_line(media, 'a=sendrecv') ||
|
||||
SDPUtil.find_line(media, 'a=recvonly') ||
|
||||
SDPUtil.find_line(media, 'a=sendonly') ||
|
||||
SDPUtil.find_line(media, 'a=inactive') ||
|
||||
'a=sendrecv').substr(2);
|
||||
}
|
||||
// TODO(gp) maybe exclude FID streams?
|
||||
Object.keys(media.sources).forEach(function(ssrc) {
|
||||
newssrcs.push({
|
||||
'ssrc': ssrc,
|
||||
'type': media.type,
|
||||
'direction': media.direction
|
||||
});
|
||||
});
|
||||
});
|
||||
console.log('new ssrcs', newssrcs);
|
||||
|
||||
// Have to clear presence map to get rid of removed streams
|
||||
connection.emuc.clearPresenceMedia();
|
||||
var i = 0;
|
||||
Object.keys(newssrcs).forEach(function (mtype) {
|
||||
i++;
|
||||
var type = mtype;
|
||||
// Change video type to screen
|
||||
if (mtype === 'video' && isUsingScreenStream) {
|
||||
type = 'screen';
|
||||
|
||||
if (newssrcs.length > 0) {
|
||||
for (var i = 1; i <= newssrcs.length; i ++) {
|
||||
// Change video type to screen
|
||||
if (newssrcs[i-1].type === 'video' && isUsingScreenStream) {
|
||||
newssrcs[i-1].type = 'screen';
|
||||
}
|
||||
connection.emuc.addMediaToPresence(i,
|
||||
newssrcs[i-1].type, newssrcs[i-1].ssrc, newssrcs[i-1].direction);
|
||||
}
|
||||
connection.emuc.addMediaToPresence(i, type, newssrcs[mtype], directions[mtype]);
|
||||
});
|
||||
if (i > 0) {
|
||||
|
||||
connection.emuc.sendPresence();
|
||||
}
|
||||
});
|
||||
|
@ -642,7 +664,7 @@ $(document).bind('joined.muc', function (event, jid, info) {
|
|||
ContactList.addContact(jid);
|
||||
|
||||
// Once we've joined the muc show the toolbar
|
||||
Toolbar.showToolbar();
|
||||
ToolbarToggler.showToolbar();
|
||||
|
||||
if (info.displayName)
|
||||
$(document).trigger('displaynamechanged',
|
||||
|
@ -652,7 +674,7 @@ $(document).bind('joined.muc', function (event, jid, info) {
|
|||
$(document).bind('entered.muc', function (event, jid, info, pres) {
|
||||
console.log('entered', jid, info);
|
||||
|
||||
console.log('is focus?' + focus ? 'true' : 'false');
|
||||
console.log('is focus? ' + (focus ? 'true' : 'false'));
|
||||
|
||||
// Add Peer's container
|
||||
VideoLayout.ensurePeerContainerExists(jid);
|
||||
|
@ -877,6 +899,7 @@ function getConferenceHandler() {
|
|||
}
|
||||
|
||||
function toggleVideo() {
|
||||
buttonClick("#video", "icon-camera icon-camera-disabled");
|
||||
if (!(connection && connection.jingle.localVideo))
|
||||
return;
|
||||
|
||||
|
@ -1140,7 +1163,12 @@ $(document).ready(function () {
|
|||
Chat.init();
|
||||
|
||||
$('body').popover({ selector: '[data-toggle=popover]',
|
||||
trigger: 'click hover'});
|
||||
trigger: 'click hover',
|
||||
content: function() {
|
||||
return this.getAttribute("content") +
|
||||
KeyboardShortcut.getShortcut(this.getAttribute("shortcut"));
|
||||
}
|
||||
});
|
||||
|
||||
// Set the defaults for prompt dialogs.
|
||||
jQuery.prompt.setDefaults({persistent: false});
|
||||
|
|
|
@ -21,6 +21,11 @@ var BottomToolbar = (function (my) {
|
|||
ContactList.toggleContactList();
|
||||
};
|
||||
|
||||
my.toggleFilmStrip = function() {
|
||||
var filmstrip = $("#remoteVideos");
|
||||
filmstrip.toggleClass("hidden");
|
||||
};
|
||||
|
||||
|
||||
$(document).bind("remotevideo.resized", function (event, width, height) {
|
||||
var bottom = (height - $('#bottomToolbar').outerHeight())/2 + 18;
|
||||
|
|
21
chat.js
|
@ -207,7 +207,7 @@ var Chat = (function (my) {
|
|||
// Undock the toolbar when the chat is shown and if we're in a
|
||||
// video mode.
|
||||
if (VideoLayout.isLargeVideoVisible())
|
||||
Toolbar.dockToolbar(false);
|
||||
ToolbarToggler.dockToolbar(false);
|
||||
|
||||
videospace.animate({right: chatSize[0],
|
||||
width: videospaceWidth,
|
||||
|
@ -252,15 +252,18 @@ var Chat = (function (my) {
|
|||
|
||||
$('#chatspace').show("slide", { direction: "right",
|
||||
queue: false,
|
||||
duration: 500});
|
||||
duration: 500,
|
||||
complete: function () {
|
||||
// Request the focus in the nickname field or the chat input field.
|
||||
if ($('#nickname').css('visibility') === 'visible') {
|
||||
$('#nickinput').focus();
|
||||
} else {
|
||||
$('#usermsg').focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Request the focus in the nickname field or the chat input field.
|
||||
if ($('#nickname').css('visibility') === 'visible')
|
||||
$('#nickinput').focus();
|
||||
else {
|
||||
$('#usermsg').focus();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -333,7 +336,7 @@ var Chat = (function (my) {
|
|||
if (unreadMessages) {
|
||||
unreadMsgElement.innerHTML = unreadMessages.toString();
|
||||
|
||||
Toolbar.dockToolbar(true);
|
||||
ToolbarToggler.dockToolbar(true);
|
||||
|
||||
var chatButtonElement
|
||||
= document.getElementById('chatButton').parentNode;
|
||||
|
|
|
@ -13,13 +13,16 @@ var config = {
|
|||
bosh: '//jitsi-meet.example.com/http-bind', // FIXME: use xep-0156 for that
|
||||
desktopSharing: 'ext', // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
|
||||
chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
|
||||
desktopSharingSources: ['screen', 'window'],
|
||||
minChromeExtVersion: '0.1', // Required version of Chrome extension
|
||||
enableRtpStats: true, // Enables RTP stats processing
|
||||
openSctp: true, // Toggle to enable/disable SCTP channels
|
||||
channelLastN: -1, // The default value of the channel attribute last-n.
|
||||
// useRtcpMux: true,
|
||||
// useBundle: true,
|
||||
useRtcpMux: true,
|
||||
useBundle: true,
|
||||
enableRecording: false,
|
||||
enableWelcomePage: false,
|
||||
enableSimulcast: false,
|
||||
useNativeSimulcast: false,
|
||||
isBrand: false
|
||||
};
|
||||
|
|
|
@ -143,7 +143,7 @@ var ContactList = (function (my) {
|
|||
// Undock the toolbar when the chat is shown and if we're in a
|
||||
// video mode.
|
||||
if (VideoLayout.isLargeVideoVisible())
|
||||
Toolbar.dockToolbar(false);
|
||||
ToolbarToggler.dockToolbar(false);
|
||||
|
||||
videospace.animate({right: chatSize[0],
|
||||
width: videospaceWidth,
|
||||
|
|
|
@ -103,3 +103,6 @@
|
|||
.icon-reload:before {
|
||||
content: "\e618";
|
||||
}
|
||||
.icon-filmstrip:before {
|
||||
content: "\e619";
|
||||
}
|
|
@ -19,6 +19,11 @@
|
|||
width:auto;
|
||||
border:1px solid transparent;
|
||||
z-index: 5;
|
||||
transition: bottom 2s;
|
||||
}
|
||||
|
||||
#remotevideos.hidden {
|
||||
bottom: -196px;
|
||||
}
|
||||
|
||||
.videocontainer {
|
||||
|
|
|
@ -84,6 +84,11 @@ function onDataChannel(event)
|
|||
'lastnchanged',
|
||||
[lastNEndpoints, endpointsEnteringLastN, stream]);
|
||||
}
|
||||
else if ("SimulcastLayersChangedEvent" === colibriClass)
|
||||
{
|
||||
var endpointSimulcastLayers = obj.endpointSimulcastLayers;
|
||||
$(document).trigger('simulcastlayerschanged', [endpointSimulcastLayers]);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.debug("Data channel JSON-formatted message: ", obj);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
jitsi-meet (1.0.1-1) unstable; urgency=low
|
||||
|
||||
* Initial release
|
||||
* Jitsi Meet github snapshot from 2014-07-01
|
||||
* Initial release. (Closes: #760485)
|
||||
|
||||
-- Yasen Pramatarov <yasen@bluejimp.com> Tue, 01 Jul 2014 16:31:41 +0300
|
||||
-- Damian Minkov <damencho@jitsi.org> Fri, 29 Aug 2014 16:38:14 +0200
|
||||
|
|
|
@ -4,7 +4,7 @@ Priority: extra
|
|||
Maintainer: Jitsi Team <dev@jitsi.org>
|
||||
Uploaders: Emil Ivov <emcho@jitsi.org>, Damian Minkov <damencho@jitsi.org>
|
||||
Build-Depends: debhelper (>= 8.0.0)
|
||||
Standards-Version: 3.9.3
|
||||
Standards-Version: 3.9.5
|
||||
Homepage: https://jitsi.org/meet
|
||||
|
||||
Package: jitsi-meet
|
||||
|
@ -20,8 +20,8 @@ Description: WebRTC JavaScript video conferences
|
|||
|
||||
Package: jitsi-meet-prosody
|
||||
Architecture: all
|
||||
Pre-Depends: adduser, openssl, prosody-trunk, jitsi-videobridge
|
||||
Depends: ${misc:Depends}, nginx, prosody-modules-otalk, lua-sec
|
||||
Pre-Depends: adduser, openssl, prosody | prosody-trunk, jitsi-videobridge
|
||||
Depends: ${misc:Depends}, nginx, prosody-module-turncredentials | prosody-modules-otalk, lua-sec
|
||||
Description: Prosody configuration for Jitsi Meet
|
||||
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
|
||||
Videobridge to provide high quality, scalable video conferences.
|
||||
|
|
|
@ -1 +1 @@
|
|||
debian/usr/share/doc/jitsi-meet-prosody/prosody.cfg.lua-jvb.example.gz
|
||||
debian/usr/share/doc/jitsi-meet-prosody/prosody.cfg.lua-jvb.example
|
||||
|
|
|
@ -1 +1 @@
|
|||
debian/usr/share/* usr/share/
|
||||
debian/usr/share/doc/jitsi-meet-prosody /usr/share/doc/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# postinst script for jitsi-meet-prosody
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
@ -24,14 +24,24 @@ case "$1" in
|
|||
. /etc/default/jitsi-videobridge
|
||||
|
||||
PROSODY_CONFIG_PRESENT="true"
|
||||
# if there is no prosody config extract our template
|
||||
if [ ! -f /etc/prosody/prosody.cfg.lua ]; then
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
gunzip -c /usr/share/doc/jitsi-meet-prosody/prosody.cfg.lua-jvb.example.gz > /etc/prosody/prosody.cfg.lua
|
||||
fi
|
||||
|
||||
if [ ! grep "VirtualHost \"$JVB_HOSTNAME\"" /etc/prosody/prosody.cfg.lua > /dev/null ]; then
|
||||
# if there is no config for our domain, lets create it
|
||||
if ! grep -q "VirtualHost \"$JVB_HOSTNAME\"" /etc/prosody/prosody.cfg.lua; then
|
||||
|
||||
# if its not our template, save the original and extract our template
|
||||
if ! grep -q "VirtualHost \"jitmeet.example.com\"" /etc/prosody/prosody.cfg.lua; then
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
cp /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.lua.orig
|
||||
gunzip -c /usr/share/doc/jitsi-meet-prosody/prosody.cfg.lua-jvb.example.gz > /etc/prosody/prosody.cfg.lua
|
||||
fi
|
||||
|
||||
if [ "PROSODY_CONFIG_PRESENT" = "true" ]; then
|
||||
mv /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.lua.orig
|
||||
cp /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.lua.orig
|
||||
fi
|
||||
sed -i "s/jitmeet.example.com/$JVB_HOSTNAME/g" /etc/prosody/prosody.cfg.lua
|
||||
sed -i "s/jitmeetSecret/$JVB_SECRET/g" /etc/prosody/prosody.cfg.lua
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#!/bin/sh
|
||||
# preinst script for jitsi-meet-prosody
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
|
@ -1,36 +0,0 @@
|
|||
#!/bin/sh
|
||||
# prerm script for jitsi-meet-prosody
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|purge)
|
||||
;;
|
||||
|
||||
upgrade|deconfigure)
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -1 +0,0 @@
|
|||
misc:Depends=
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Source debconf library.
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
# certificate type choice
|
||||
db_input critical jitsi-meet/cert-choice || true
|
||||
db_go
|
|
@ -1,31 +0,0 @@
|
|||
Format: http://dep.debian.net/deps/dep5
|
||||
Upstream-Name: Jitsi Meet
|
||||
Upstream-Contact: Emil Ivov <emcho@jitsi.org>
|
||||
Source: https://github.com/jitsi/jitsi-meet
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2014 Jitsi
|
||||
License: MIT
|
||||
|
||||
License: MIT
|
||||
The MIT License (MIT)
|
||||
.
|
||||
Copyright (c) 2013 ESTOS GmbH
|
||||
Copyright (c) 2013 BlueJimp SARL
|
||||
.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,2 +1,10 @@
|
|||
* usr/share/jitsi-meet/
|
||||
debian/usr/share/* usr/share/
|
||||
*.js /usr/share/jitsi-meet/
|
||||
*.json /usr/share/jitsi-meet/
|
||||
*.html /usr/share/jitsi-meet/
|
||||
*.ico /usr/share/jitsi-meet/
|
||||
libs /usr/share/jitsi-meet/
|
||||
css /usr/share/jitsi-meet/
|
||||
sounds /usr/share/jitsi-meet/
|
||||
fonts /usr/share/jitsi-meet/
|
||||
images /usr/share/jitsi-meet/
|
||||
debian/usr/share/doc/jitsi-meet /usr/share/doc/
|
||||
|
|
|
@ -17,12 +17,12 @@ set -e
|
|||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
|
||||
# nginx conf
|
||||
. /etc/default/jitsi-videobridge
|
||||
|
||||
# nginx conf
|
||||
if [ ! -f /etc/nginx/sites-available/$JVB_HOSTNAME.conf ]; then
|
||||
cp /usr/share/doc/jitsi-meet/jitsi-meet.example /etc/nginx/sites-available/$JVB_HOSTNAME.conf
|
||||
if [ ! -f /etc/nginx/sites-enabled/$JVB_HOSTNAME.conf ]; then
|
||||
|
@ -35,6 +35,39 @@ case "$1" in
|
|||
sed -i "s/#\ server_names_hash_bucket_size\ 64/\ server_names_hash_bucket_size\ 64/" /etc/nginx/nginx.conf
|
||||
fi
|
||||
|
||||
if [ ! -f /etc/ssl/$JVB_HOSTNAME.key ] || [ ! -f /etc/ssl/$JVB_HOSTNAME.crt ]; then
|
||||
# loading debconf
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
# SSL for nginx
|
||||
db_get jitsi-meet/cert-choice
|
||||
CERT_CHOICE="$RET"
|
||||
if [ "$CERT_CHOICE" = 'I have a certificate and will upload the files on the server' ]; then
|
||||
db_set jitsi-meet/cert-path-key "/etc/ssl/$JVB_HOSTNAME.key"
|
||||
db_input critical jitsi-meet/cert-path-key || true
|
||||
db_go
|
||||
db_get jitsi-meet/cert-path-key
|
||||
CERT_KEY="$RET"
|
||||
db_set jitsi-meet/cert-path-crt "/etc/ssl/$JVB_HOSTNAME.crt"
|
||||
db_input critical jitsi-meet/cert-path-crt || true
|
||||
db_go
|
||||
db_get jitsi-meet/cert-path-crt
|
||||
CERT_CRT="$RET"
|
||||
# replace self-signed certificate paths with user provided ones
|
||||
CERT_KEY_ESC=$(echo $CERT_KEY | sed 's/\./\\\./g')
|
||||
CERT_KEY_ESC=$(echo $CERT_KEY_ESC | sed 's/\//\\\//g')
|
||||
sed -i "s/ssl_certificate_key\ \/var\/lib\/prosody\/.*key/ssl_certificate_key\ $CERT_KEY_ESC/g" \
|
||||
/etc/nginx/sites-available/$JVB_HOSTNAME.conf
|
||||
CERT_CRT_ESC=$(echo $CERT_CRT | sed 's/\./\\\./g')
|
||||
CERT_CRT_ESC=$(echo $CERT_CRT_ESC | sed 's/\//\\\//g')
|
||||
sed -i "s/ssl_certificate\ \/var\/lib\/prosody\/.*crt/ssl_certificate\ $CERT_CRT_ESC/g" \
|
||||
/etc/nginx/sites-available/$JVB_HOSTNAME.conf
|
||||
fi
|
||||
|
||||
# and we're done with debconf
|
||||
db_stop
|
||||
fi
|
||||
|
||||
# jitsi meet
|
||||
chown -R www-data:www-data /usr/share/jitsi-meet/
|
||||
sed -i "s/jitsi-meet.example.com/$JVB_HOSTNAME/g" /usr/share/jitsi-meet/config.js
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#!/bin/sh
|
||||
# preinst script for jitsi-meet
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
|
@ -1,36 +0,0 @@
|
|||
#!/bin/sh
|
||||
# prerm script for jitsi-meet
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|purge)
|
||||
;;
|
||||
|
||||
upgrade|deconfigure)
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,23 @@
|
|||
Template: jitsi-meet/cert-choice
|
||||
Type: select
|
||||
__Choices: Self-signed certificate will be generated, A certificate is available and the files are uploaded on the server
|
||||
_Description: SSL certificate for the Jitsi Meet instance
|
||||
Jitsi Meet is best to be set up with an SSL certificate.
|
||||
Having no certificate, a self-signed one will be generated.
|
||||
Having a certificate signed by a recognised CA, it can be uploaded on the server
|
||||
and point its location. The default filenames will be /etc/ssl/--domain.name--.key
|
||||
for the key and /etc/ssl/--domain.name--.crt for the certificate.
|
||||
|
||||
Template: jitsi-meet/cert-path-key
|
||||
Type: string
|
||||
Default: ${default-key}
|
||||
_Description: Full local server path to the SSL key file:
|
||||
The full path to the SSL key file on the server.
|
||||
If it has not been uploaded, now is a good time to do so.
|
||||
|
||||
Template: jitsi-meet/cert-path-crt
|
||||
Type: string
|
||||
Default: ${default-crt}
|
||||
_Description: Full local server path to the SSL certificate file:
|
||||
The full path to the SSL certificate file on the server.
|
||||
If you haven't uploaded it, now is a good time to upload it in another console.
|
|
@ -0,0 +1 @@
|
|||
[type: gettext/rfc822deb] jitsi-meet.templates
|
|
@ -0,0 +1,75 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: jitsi-meet\n"
|
||||
"Report-Msgid-Bugs-To: jitsi-meet@packages.debian.org\n"
|
||||
"POT-Creation-Date: 2014-09-03 17:26+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#. Type: select
|
||||
#. Choices
|
||||
#: ../jitsi-meet.templates:1001
|
||||
msgid "Self-signed certificate will be generated"
|
||||
msgstr ""
|
||||
|
||||
#. Type: select
|
||||
#. Choices
|
||||
#: ../jitsi-meet.templates:1001
|
||||
msgid "A certificate is available and the files are uploaded on the server"
|
||||
msgstr ""
|
||||
|
||||
#. Type: select
|
||||
#. Description
|
||||
#: ../jitsi-meet.templates:1002
|
||||
msgid "SSL certificate for the Jitsi Meet instance"
|
||||
msgstr ""
|
||||
|
||||
#. Type: select
|
||||
#. Description
|
||||
#: ../jitsi-meet.templates:1002
|
||||
msgid ""
|
||||
"Jitsi Meet is best to be set up with an SSL certificate. Having no "
|
||||
"certificate, a self-signed one will be generated. Having a certificate "
|
||||
"signed by a recognised CA, it can be uploaded on the server and point its "
|
||||
"location. The default filenames will be /etc/ssl/--domain.name--.key for the "
|
||||
"key and /etc/ssl/--domain.name--.crt for the certificate."
|
||||
msgstr ""
|
||||
|
||||
#. Type: string
|
||||
#. Description
|
||||
#: ../jitsi-meet.templates:2001
|
||||
msgid "Full local server path to the SSL key file:"
|
||||
msgstr ""
|
||||
|
||||
#. Type: string
|
||||
#. Description
|
||||
#: ../jitsi-meet.templates:2001
|
||||
msgid ""
|
||||
"The full path to the SSL key file on the server. If it has not been "
|
||||
"uploaded, now is a good time to do so."
|
||||
msgstr ""
|
||||
|
||||
#. Type: string
|
||||
#. Description
|
||||
#: ../jitsi-meet.templates:3001
|
||||
msgid "Full local server path to the SSL certificate file:"
|
||||
msgstr ""
|
||||
|
||||
#. Type: string
|
||||
#. Description
|
||||
#: ../jitsi-meet.templates:3001
|
||||
msgid ""
|
||||
"The full path to the SSL certificate file on the server. If you haven't "
|
||||
"uploaded it, now is a good time to upload it in another console."
|
||||
msgstr ""
|
|
@ -10,7 +10,6 @@
|
|||
#export DH_VERBOSE=1
|
||||
|
||||
%:
|
||||
dh_install
|
||||
dh_installdirs
|
||||
dh $@
|
||||
|
||||
override_dh_install-indep:
|
||||
dh_install -Xdebian -Xdoc -XINSTALL.md -XLICENSE -XREADME.md usr/share/jitsi-meet/
|
||||
|
|
|
@ -16,4 +16,3 @@ debian/usr/share/jitsi-meet/images/popupPointer.png
|
|||
debian/usr/share/jitsi-meet/images/favicon.ico
|
||||
debian/usr/share/doc/jitsi-meet/changelog.Debian.gz
|
||||
debian/usr/share/doc/jitsi-meet-prosody/changelog.Debian.gz
|
||||
debian/usr/share/doc/jitsi-meet-prosody/prosody.cfg.lua-jvb.example.gz
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# The strophe.min.js file, from http://strophe.im/strophejs/ (https://github.com/strophe/strophejs)
|
||||
# contains the source with minimum space characters
|
||||
source-is-missing libs/strophe/strophe.jingle.bundle.js
|
|
@ -0,0 +1,210 @@
|
|||
-- Prosody XMPP Server Configuration
|
||||
--
|
||||
-- Information on configuring Prosody can be found on our
|
||||
-- website at http://prosody.im/doc/configure
|
||||
--
|
||||
-- Tip: You can check that the syntax of this file is correct
|
||||
-- when you have finished by running: prosodyctl check config
|
||||
-- If there are any errors, it will let you know what and where
|
||||
-- they are, otherwise it will keep quiet.
|
||||
--
|
||||
-- Good luck, and happy Jabbering!
|
||||
|
||||
|
||||
---------- Server-wide settings ----------
|
||||
-- Settings in this section apply to the whole server and are the default settings
|
||||
-- for any virtual hosts
|
||||
|
||||
-- This is a (by default, empty) list of accounts that are admins
|
||||
-- for the server. Note that you must create the accounts separately
|
||||
-- (see http://prosody.im/doc/creating_accounts for info)
|
||||
-- Example: admins = { "user1@example.com", "user2@example.net" }
|
||||
admins = { }
|
||||
daemonize = true
|
||||
cross_domain_bosh = true;
|
||||
component_ports = { 5347 }
|
||||
|
||||
|
||||
-- Enable use of libevent for better performance under high load
|
||||
-- For more information see: http://prosody.im/doc/libevent
|
||||
--use_libevent = true
|
||||
|
||||
-- This is the list of modules Prosody will load on startup.
|
||||
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
|
||||
-- Documentation on modules can be found at: http://prosody.im/doc/modules
|
||||
modules_enabled = {
|
||||
|
||||
-- Generally required
|
||||
"roster"; -- Allow users to have a roster. Recommended ;)
|
||||
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
|
||||
"tls"; -- Add support for secure TLS on c2s/s2s connections
|
||||
"dialback"; -- s2s dialback support
|
||||
"disco"; -- Service discovery
|
||||
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
|
||||
|
||||
-- Not essential, but recommended
|
||||
"private"; -- Private XML storage (for room bookmarks, etc.)
|
||||
"vcard"; -- Allow users to set vCards
|
||||
|
||||
-- These are commented by default as they have a performance impact
|
||||
--"privacy"; -- Support privacy lists
|
||||
"compression"; -- Stream compression (requires the lua-zlib package installed)
|
||||
|
||||
-- Nice to have
|
||||
"version"; -- Replies to server version requests
|
||||
"uptime"; -- Report how long server has been running
|
||||
"time"; -- Let others know the time here on this server
|
||||
"ping"; -- Replies to XMPP pings with pongs
|
||||
"pep"; -- Enables users to publish their mood, activity, playing music and more
|
||||
"register"; -- Allow users to register on this server using a client and change passwords
|
||||
|
||||
-- Admin interfaces
|
||||
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
|
||||
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
|
||||
|
||||
-- HTTP modules
|
||||
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
|
||||
--"http_files"; -- Serve static files from a directory over HTTP
|
||||
|
||||
-- Other specific functionality
|
||||
--"groups"; -- Shared roster support
|
||||
--"announce"; -- Send announcement to all online users
|
||||
--"welcome"; -- Welcome users who register accounts
|
||||
--"watchregistrations"; -- Alert admins of registrations
|
||||
--"motd"; -- Send a message to users when they log in
|
||||
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
|
||||
-- jitmeet
|
||||
--"smacks";
|
||||
--"carbons";
|
||||
--"mam";
|
||||
--"lastactivity";
|
||||
--"offline";
|
||||
"pubsub";
|
||||
--"adhoc";
|
||||
--"websocket";
|
||||
--"http_altconnect";
|
||||
"turncredentials";
|
||||
}
|
||||
|
||||
-- These modules are auto-loaded, but should you want
|
||||
-- to disable them then uncomment them here:
|
||||
modules_disabled = {
|
||||
-- "offline"; -- Store offline messages
|
||||
-- "c2s"; -- Handle client connections
|
||||
-- "s2s"; -- Handle server-to-server connections
|
||||
}
|
||||
|
||||
-- Disable account creation by default, for security
|
||||
-- For more information see http://prosody.im/doc/creating_accounts
|
||||
allow_registration = false
|
||||
|
||||
-- These are the SSL/TLS-related settings. If you don't want
|
||||
-- to use SSL/TLS, you may comment or remove this
|
||||
ssl = {
|
||||
key = "/etc/prosody/certs/localhost.key";
|
||||
certificate = "/etc/prosody/certs/localhost.crt";
|
||||
}
|
||||
|
||||
-- Force clients to use encrypted connections? This option will
|
||||
-- prevent clients from authenticating unless they are using encryption.
|
||||
|
||||
-- c2s_require_encryption = true
|
||||
|
||||
-- Force certificate authentication for server-to-server connections?
|
||||
-- This provides ideal security, but requires servers you communicate
|
||||
-- with to support encryption AND present valid, trusted certificates.
|
||||
-- NOTE: Your version of LuaSec must support certificate verification!
|
||||
-- For more information see http://prosody.im/doc/s2s#security
|
||||
|
||||
-- s2s_secure_auth = false
|
||||
|
||||
-- Many servers don't support encryption or have invalid or self-signed
|
||||
-- certificates. You can list domains here that will not be required to
|
||||
-- authenticate using certificates. They will be authenticated using DNS.
|
||||
|
||||
--s2s_insecure_domains = { "gmail.com" }
|
||||
|
||||
-- Even if you leave s2s_secure_auth disabled, you can still require valid
|
||||
-- certificates for some domains by specifying a list here.
|
||||
|
||||
--s2s_secure_domains = { "jabber.org" }
|
||||
|
||||
-- Required for init scripts and prosodyctl
|
||||
pidfile = "/var/run/prosody/prosody.pid"
|
||||
|
||||
-- Select the authentication backend to use. The 'internal' providers
|
||||
-- use Prosody's configured data storage to store the authentication data.
|
||||
-- To allow Prosody to offer secure authentication mechanisms to clients, the
|
||||
-- default provider stores passwords in plaintext. If you do not trust your
|
||||
-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed
|
||||
-- for information about using the hashed backend.
|
||||
|
||||
-- authentication = "internal_plain"
|
||||
authentication = "internal_hashed"
|
||||
|
||||
-- Select the storage backend to use. By default Prosody uses flat files
|
||||
-- in its configured data directory, but it also supports more backends
|
||||
-- through modules. An "sql" backend is included by default, but requires
|
||||
-- additional dependencies. See http://prosody.im/doc/storage for more info.
|
||||
|
||||
--storage = "sql" -- Default is "internal"
|
||||
|
||||
-- For the "sql" backend, you can uncomment *one* of the below to configure:
|
||||
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
|
||||
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
|
||||
|
||||
storage = {archive2 = "sql2"}
|
||||
sql = { driver = "SQLite3", database = "prosody.sqlite" }
|
||||
default_archive_policy = "roster"
|
||||
|
||||
-- Logging configuration
|
||||
-- For advanced logging see http://prosody.im/doc/logging
|
||||
log = {
|
||||
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
|
||||
error = "/var/log/prosody/prosody.err";
|
||||
"*syslog";
|
||||
}
|
||||
|
||||
----------- Virtual hosts -----------
|
||||
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
|
||||
-- Settings under each VirtualHost entry apply *only* to that host.
|
||||
|
||||
-- VirtualHost "localhost"
|
||||
|
||||
VirtualHost "jitmeet.example.com"
|
||||
-- enabled = false -- Remove this line to enable this host
|
||||
authentication = "anonymous"
|
||||
-- Assign this host a certificate for TLS, otherwise it would use the one
|
||||
-- set in the global section (if any).
|
||||
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
|
||||
-- use the global one.
|
||||
ssl = {
|
||||
key = "/etc/prosody/certs/jitmeet.example.com.key";
|
||||
certificate = "/etc/prosody/certs/jitmeet.example.com.crt";
|
||||
}
|
||||
|
||||
------ Components ------
|
||||
-- You can specify components to add hosts that provide special services,
|
||||
-- like multi-user conferences, and transports.
|
||||
-- For more information on components, see http://prosody.im/doc/components
|
||||
|
||||
---Set up a MUC (multi-user chat) room server on conference.example.com:
|
||||
--Component "conference.example.com" "muc"
|
||||
|
||||
-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers:
|
||||
--Component "proxy.example.com" "proxy65"
|
||||
|
||||
---Set up an external component (default component port is 5347)
|
||||
--
|
||||
-- External components allow adding various services, such as gateways/
|
||||
-- transports to other networks like ICQ, MSN and Yahoo. For more info
|
||||
-- see: http://prosody.im/doc/components#adding_an_external_component
|
||||
--
|
||||
--Component "gateway.example.com"
|
||||
-- component_secret = "password"
|
||||
|
||||
Component "conference.jitmeet.example.com" "muc"
|
||||
|
||||
Component "jitsi-videobridge.jitmeet.example.com"
|
||||
component_secret = "jitmeetSecret"
|
|
@ -23,14 +23,4 @@ server {
|
|||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
|
||||
# xmpp websockets
|
||||
location /xmpp-websocket {
|
||||
proxy_pass http://localhost:5280;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
tcp_nodelay on;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ function doGetStreamFromExtension(streamCallback, failCallback) {
|
|||
// Sends 'getStream' msg to the extension. Extension id must be defined in the config.
|
||||
chrome.runtime.sendMessage(
|
||||
config.chromeExtensionId,
|
||||
{ getStream: true},
|
||||
{ getStream: true, sources: config.desktopSharingSources },
|
||||
function (response) {
|
||||
if (!response) {
|
||||
failCallback(chrome.runtime.lastError);
|
||||
|
|
|
@ -46,7 +46,7 @@ var Etherpad = (function (my) {
|
|||
largeVideo.css({opacity: '0'});
|
||||
} else {
|
||||
VideoLayout.setLargeVideoVisible(false);
|
||||
Toolbar.dockToolbar(true);
|
||||
ToolbarToggler.dockToolbar(true);
|
||||
}
|
||||
|
||||
$('#etherpad>iframe').fadeIn(300, function () {
|
||||
|
@ -64,7 +64,7 @@ var Etherpad = (function (my) {
|
|||
if (!isPresentation) {
|
||||
$('#largeVideo').fadeIn(300, function () {
|
||||
VideoLayout.setLargeVideoVisible(true);
|
||||
Toolbar.dockToolbar(false);
|
||||
ToolbarToggler.dockToolbar(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -32,4 +32,5 @@
|
|||
<glyph unicode="" d="M513.087 224.534c0-141.673-114.855-256.526-256.554-256.526-141.674 0-256.534 114.851-256.534 256.526 0 141.692 114.861 256.553 256.534 256.553 141.7 0 256.554-114.861 256.554-256.553zM256.534-31.993c67.863 0 129.556 26.356 175.437 69.37-4.858 5.825-11.276 10.557-19.557 14.171-29.467 12.873-58.313 27.128-87.267 41.128-20.935 10.161-19.702 33.293-12.82 43.029 4.471 6.346 8.402 12.999 8.864 21.373 0.166 3.084 3.12 7.142 5.945 8.761 9.802 5.652 14.349 14.873 18.802 24.43 1.17 2.515 2.777 4.945 4.615 7.038 3.185 3.622 4.612 7.218 2.286 11.971-0.543 1.104 0.502 3.12 1.053 4.637 1.619 4.534 3.866 8.901 4.93 13.558 1.335 5.774 2.029 11.74 2.351 17.661 0.14 2.451-2.272 5.092-2.017 7.493 1.31 12.011-5.471 21.136-9.299 31.579-4.688 12.857-13.885 20.91-22.002 30.485-1.529 1.812-1.964 4.919-2.094 7.476-0.269 5.49-2.53 8.207-8.272 7.462-2.299-0.3-4.805-0.943-6.921-0.378-1.864 0.494-4.663 2.362-4.767 3.802-0.577 7.269-3.106 8.465-10.533 7.238-4.648-0.772-10.697 3.429-15.257 6.601-3.816 2.646-7.104 3.777-11.534 2.69-1.849-0.45-4.341-0.373-5.908 0.547-1.671 0.988-3.303 1.592-4.933 1.919v0.276c-0.36-0.007-0.745-0.065-1.104-0.108-0.361 0.044-0.72 0.103-1.078 0.108v-0.276c-1.645-0.327-3.287-0.931-4.945-1.919-1.556-0.918-4.046-0.996-5.899-0.547-4.443 1.087-7.724-0.044-11.532-2.69-4.578-3.173-10.611-7.373-15.259-6.601-7.431 1.226-9.97 0.031-10.547-7.238-0.109-1.439-2.897-3.308-4.758-3.802-2.139-0.565-4.624 0.077-6.944 0.378-5.728 0.745-7.994-1.971-8.258-7.462-0.131-2.555-0.565-5.665-2.095-7.476-8.111-9.575-17.308-17.629-22.009-30.485-3.814-10.443-10.602-19.568-9.285-31.579 0.256-2.401-2.152-5.042-2.023-7.493 0.327-5.923 1.020-11.888 2.351-17.661 1.065-4.656 3.313-9.024 4.945-13.558 0.547-1.516 1.587-3.531 1.041-4.637-2.325-4.754-0.894-8.351 2.291-11.971 1.837-2.094 3.437-4.523 4.612-7.038 4.45-9.555 8.996-18.779 18.798-24.43 2.827-1.619 5.78-5.676 5.952-8.761 0.457-8.374 4.387-15.027 8.869-21.373 6.873-9.735 7.951-32.623-12.837-43.029-28.76-14.386-57.8-28.255-87.251-41.128-8.285-3.615-14.704-8.347-19.561-14.169 45.88-43.015 107.569-69.372 175.422-69.372z" horiz-adv-x="513" />
|
||||
<glyph unicode="" d="M32.887 258.374c5.026 4.679 12.994 10.886 21.642 16.349 25.668 16.31 54.057 25.449 83.415 32.066 24.381 5.475 49.123 8.444 74.033 10.101 27.877 1.877 55.779 1.89 83.696 0.399 19.972-1.092 39.843-3.251 59.56-6.606 21.978-3.753 43.519-8.997 64.392-16.875 12.209-4.587 24.086-10.053 35.267-16.786 14.858-8.946 28.276-19.612 38.61-33.674 10.409-14.151 15.861-30.204 16.914-47.696 0.873-13.701 0.358-27.349-2.828-40.794-1.438-6.041-4.113-11.567-8.277-16.193-5.709-6.324-13.212-8.51-21.386-8.818-10.231-0.334-20.205 2.057-30.18 4.113-19.456 3.985-38.918 8.123-58.349 12.364-7.069 1.517-14.344 2.546-20.825 6.298-11.154 6.478-17.223 15.887-17.017 28.892 0.129 8.435 1.108 16.891 1.235 25.348 0.156 12.505-4.962 22.581-15.449 29.521-7.197 4.769-15.347 7.456-23.726 9.333-20.206 4.523-40.693 5.089-61.281 5.025-14.411-0.063-28.791-0.834-43.047-3.071-9.974-1.581-19.781-3.906-28.866-8.507-12.159-6.182-19.677-15.732-20.036-29.676-0.22-8.175 0.487-16.401 0.964-24.575 0.321-5.911-0.040-11.723-2.648-17.144-4.63-9.692-12.468-15.836-22.685-18.482-11.323-2.933-22.802-5.27-34.252-7.611-19.051-3.882-38.108-7.684-57.208-11.259-7.263-1.387-14.627-0.976-21.567 1.801-9.371 3.728-14.462 11.387-17.069 20.668-3.548 12.699-3.921 25.757-3.483 38.865 0.45 13.52 2.942 26.618 9.202 38.803 4.897 9.532 11.246 17.977 21.246 27.821z" horiz-adv-x="513" />
|
||||
<glyph unicode="" d="M398.543 56.151c-0.029 0.082-0.060 0.164-0.080 0.243-35.7-22.819-75.891-34.966-117.012-34.966-0.007 0-0.010 0-0.014 0-61.26 0-118.75 26.386-157.734 72.37-49.889 58.849-67.126 164.977-36.511 213.894 2.002-0.831 3.938-1.616 5.84-2.387 6.793-2.756 13.207-5.358 21.153-9.548 3.031-1.601 6.169-2.406 9.337-2.406 5.857 0 11.3 2.824 14.924 7.743 3.907 5.309 5.156 12.389 3.269 18.476l-1.762 5.705c-5.344 17.295-10.862 35.177-17.106 52.539-4.992 13.882-11.2 31.163-29.613 31.163-6.028 0-13.019-1.828-23.365-6.102-22.147-9.159-35.529-14.981-57.267-24.905-7.551-3.444-12.617-11.349-12.601-19.672 0.014-7.921 4.496-14.668 11.988-18.058 9.104-4.128 15.268-6.858 21.734-9.723l5.343-2.377c-50.969-129.551 12.401-263.229 105.657-319.606 41.749-25.237 89.25-38.57 137.385-38.57h0.021c51.36 0 102.781 15.55 142.25 42.599-15.865 14.401-22.783 34.584-25.836 43.586zM549.101 105.045c-9.057 4.288-15.178 7.129-21.611 10.122l-5.248 2.446c53.224 128.634-7.784 263.401-100.034 321.394-42.68 26.832-91.562 41.016-141.358 41.016-52.424 0-103.205-15.297-142.983-43.083l-2.692-1.882c15.798-13.782 22.93-33.394 26.459-43.205 36.463 23.97 77.838 36.704 119.947 36.704 62.704 0 121.071-27.392 160.147-75.158 48.841-59.724 64.219-166.128 32.749-214.508-1.995 0.868-3.908 1.692-5.812 2.499-6.736 2.88-13.102 5.59-20.977 9.911-3.101 1.712-6.322 2.577-9.606 2.577-5.793 0-11.2-2.779-14.845-7.634-3.906-5.217-5.239-12.216-3.483-18.257l1.639-5.651c5.048-17.423 10.265-35.428 16.206-52.921 4.794-14.119 10.757-31.691 29.589-31.691 5.921 0 12.788 1.712 22.94 5.7 22.175 8.719 35.66 14.3 57.704 23.889 7.595 3.312 12.801 11.126 12.929 19.447 0.14 7.911-4.222 14.75-11.663 18.284z" horiz-adv-x="561" />
|
||||
<glyph unicode="" d="M23.497 480.85c230.617 0 276.897 0 507.512 0 17.96 0 26.678-12.98 26.678-28.98-0.29-151.63-0.163-303.244-0.225-454.904 0-21.992-6.601-28.529-28.851-28.529-221.536-0.063-278.226-0.063-499.776 0-22.267 0-28.899 6.505-28.899 28.529-0.049 151.629 0.242 304.036-0.046 455.664-0.017 13.105 5.651 26.88 23.608 28.219zM155.702 225.149c0-59.522-0.036-86.084 0.029-145.625 0.018-25.022 5.604-30.525 31.060-30.525 116.676 0 68.537 0 185.261 0 23.538 0 29.625 5.991 29.625 29.048 0.063 119.555 0.063 173.169 0 292.695 0 24.069-5.344 29.495-28.884 29.495-117.661 0.050-70.422 0.050-188.078 0-23.522 0-28.965-5.522-28.983-29.445-0.065-59.554-0.029-86.105-0.029-145.643zM76.972 419.283c-37.465-0.031-33.343 2.979-33.422-33.343-0.1-31.975-3.527-31.767 31.264-31.686 36.499 0.097 33.6-1.882 33.651 33.777 0 33.861 2.043 31.298-31.493 31.251zM481.822 419.283c-35.579-0.017-32.78 3.092-32.875-32.682-0.065-33.651-2.254-32.346 32.264-32.346 36.544 0 32.649-1.015 32.649 33.119-0.001 34.323 3.478 31.955-32.038 31.909zM108.414 61.204c0.18 36.547 2.32 33.457-33.679 33.585-34.052 0.096-31.285 1.382-31.203-31.655 0.065-36.738-3.477-33.26 33.537-33.325 33.021-0.033 31.571-3.028 31.346 31.394zM513.859 62.2c0.067 34.167 3.221 32.652-31.649 32.589-35.066-0.066-33.328 2.897-33.264-32.652 0.065-35.322-2.192-32.361 31.878-32.329 35.998 0.066 33.101-3.349 33.034 32.392zM513.859 171.038c0 35.275 3.61 33.421-33.743 33.261-0.449 0-0.937 0-1.419 0-29.688 0-29.688 0-29.688-29.012 0-38.961-3.221-34.968 34.647-35.098 33.038-0.193 30.269-1.546 30.202 30.849zM75.653 244.936c34.147-0.082 32.907-2.784 32.812 31.491-0.097 35.564 2.448 32.459-33.007 32.505-34.953 0.050-31.907 2.352-31.942-31.989-0.031-33.715-2.85-32.231 32.138-32.007zM480.632 244.936c36.256-0.129 33.295-2.302 33.228 32.247 0 34.279 3.092 31.769-32.134 31.749-35.098-0.014-32.843 3.026-32.749-32.747 0.066-31.25 0.034-31.25 31.655-31.25zM75.2 140.19c35.502 0 33.329-3.284 33.233 32.264-0.082 31.847-0.018 31.75-32.507 31.878-35.403 0.129-32.411 1.337-32.411-31.878 0.018-34.584-2.959-32.394 31.684-32.264z" horiz-adv-x="558" />
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
|
@ -1,6 +1,34 @@
|
|||
{
|
||||
"IcoMoonType": "selection",
|
||||
"icons": [
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M46.993-1.7c461.234 0 553.793 0 1015.024 0 35.919 0 53.356 25.959 53.356 57.959-0.581 303.259-0.325 606.488-0.449 909.809 0 43.984-13.203 57.058-57.703 57.058-443.072 0.126-556.453 0.126-999.553 0-44.534 0-57.799-13.009-57.799-57.058-0.098-303.257 0.485-608.072-0.093-911.329-0.034-26.21 11.301-53.761 47.217-56.439zM311.405 509.702c0 119.045-0.072 172.168 0.057 291.249 0.036 50.043 11.208 61.050 62.12 61.050 233.352 0 137.075 0 370.522 0 47.075 0 59.249-11.982 59.249-58.095 0.126-239.111 0.126-346.338 0-585.389 0-48.138-10.687-58.991-57.768-58.991-235.323-0.101-140.844-0.101-376.157 0-47.044 0-57.93 11.043-57.966 58.89-0.129 119.109-0.057 172.209-0.057 291.287zM153.944 121.434c-74.929 0.062-66.687-5.958-66.845 66.685-0.201 63.95-7.054 63.534 62.528 63.372 72.999-0.194 67.201 3.764 67.302-67.554 0-67.722 4.087-62.595-62.985-62.502zM963.644 121.434c-71.159 0.034-65.56-6.185-65.751 65.364-0.129 67.302-4.508 64.693 64.528 64.693 73.089 0 65.299 2.031 65.299-66.238-0.003-68.646 6.956-63.911-64.076-63.818zM216.828 837.592c0.359-73.094 4.639-66.914-67.358-67.17-68.104-0.191-62.569-2.763-62.407 63.31 0.129 73.476-6.954 66.52 67.074 66.649 66.042 0.065 63.142 6.056 62.691-62.789zM1027.718 835.6c0.134-68.334 6.443-65.304-63.297-65.178-70.132 0.132-66.656-5.793-66.527 65.304 0.129 70.645-4.384 64.721 63.756 64.657 71.995-0.132 66.202 6.698 66.068-64.783zM1027.718 617.923c0-70.55 7.219-66.842-67.485-66.522-0.898 0-1.873 0-2.838 0-59.375 0-59.375 0-59.375 58.023 0 77.922-6.443 69.936 69.293 70.196 66.076 0.387 60.539 3.091 60.405-61.697zM151.307 470.127c68.295 0.163 65.815 5.568 65.624-62.982-0.194-71.128 4.895-64.917-66.014-65.010-69.905-0.101-63.813-4.704-63.885 63.978-0.062 67.431-5.7 64.463 64.275 64.014zM961.263 470.127c72.511 0.258 66.589 4.603 66.455-64.494 0-68.558 6.185-63.537-64.267-63.498-70.196 0.028-65.686-6.053-65.498 65.493 0.132 62.5 0.067 62.5 63.31 62.5zM150.399 679.62c71.004 0 66.659 6.567 66.466-64.528-0.163-63.694-0.036-63.501-65.013-63.756-70.805-0.258-64.822-2.673-64.822 63.756 0.036 69.167-5.919 64.788 63.369 64.528z"
|
||||
],
|
||||
"attrs": [
|
||||
{}
|
||||
],
|
||||
"width": 1115,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"filmstrip"
|
||||
]
|
||||
},
|
||||
"attrs": [
|
||||
{}
|
||||
],
|
||||
"properties": {
|
||||
"order": 26,
|
||||
"id": 29,
|
||||
"prevSize": 32,
|
||||
"code": 58905,
|
||||
"name": "filmstrip",
|
||||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 0
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
|
@ -33,7 +61,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 0
|
||||
"iconIdx": 1
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -61,7 +89,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 1
|
||||
"iconIdx": 2
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -89,7 +117,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 2
|
||||
"iconIdx": 3
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -128,7 +156,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 3
|
||||
"iconIdx": 4
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -151,7 +179,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 4
|
||||
"iconIdx": 5
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -174,7 +202,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 5
|
||||
"iconIdx": 6
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -198,7 +226,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 6
|
||||
"iconIdx": 7
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -223,7 +251,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 7
|
||||
"iconIdx": 8
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -246,7 +274,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 8
|
||||
"iconIdx": 9
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -270,7 +298,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 9
|
||||
"iconIdx": 10
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -294,7 +322,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 10
|
||||
"iconIdx": 11
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -316,7 +344,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 11
|
||||
"iconIdx": 12
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -340,7 +368,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 12
|
||||
"iconIdx": 13
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -364,7 +392,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 13
|
||||
"iconIdx": 14
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -391,7 +419,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 14
|
||||
"iconIdx": 15
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -415,7 +443,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 15
|
||||
"iconIdx": 16
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -439,7 +467,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 16
|
||||
"iconIdx": 17
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -464,7 +492,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 17
|
||||
"iconIdx": 18
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -486,7 +514,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 18
|
||||
"iconIdx": 19
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -509,7 +537,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 19
|
||||
"iconIdx": 20
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -531,7 +559,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 20
|
||||
"iconIdx": 21
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -554,7 +582,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 21
|
||||
"iconIdx": 22
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -577,7 +605,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 22
|
||||
"iconIdx": 23
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -601,7 +629,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 23
|
||||
"iconIdx": 24
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
|
@ -624,7 +652,7 @@
|
|||
"ligatures": ""
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 24
|
||||
"iconIdx": 25
|
||||
}
|
||||
],
|
||||
"height": 1024,
|
||||
|
@ -637,7 +665,9 @@
|
|||
"fontPref": {
|
||||
"prefix": "icon-",
|
||||
"metadata": {
|
||||
"fontFamily": "jitsi"
|
||||
"fontFamily": "jitsi",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 0
|
||||
},
|
||||
"metrics": {
|
||||
"emSize": 512,
|
||||
|
|
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
59
index.html
|
@ -10,6 +10,7 @@
|
|||
<meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta itemprop="image" content="/images/jitsilogo.png"/>
|
||||
<script src="libs/jquery-2.1.1.min.js"></script>
|
||||
<script src="simulcast.js?v=1"></script><!-- simulcast handling -->
|
||||
<script src="libs/strophe/strophe.jingle.adapter.js?v=1"></script><!-- strophe.jingle bundles -->
|
||||
<script src="libs/strophe/strophe.jingle.bundle.js?v=8"></script>
|
||||
<script src="libs/strophe/strophe.jingle.js?v=1"></script>
|
||||
|
@ -17,6 +18,7 @@
|
|||
<script src="libs/strophe/strophe.jingle.sdp.util.js?v=1"></script>
|
||||
<script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script>
|
||||
<script src="libs/strophe/strophe.jingle.session.js?v=1"></script>
|
||||
<script src="libs/strophe/strophe.util.js"></script>
|
||||
<script src="libs/colibri/colibri.focus.js?v=8"></script><!-- colibri focus implementation -->
|
||||
<script src="libs/colibri/colibri.session.js?v=1"></script>
|
||||
<script src="libs/jquery-ui.js"></script>
|
||||
|
@ -29,13 +31,13 @@
|
|||
<script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
|
||||
<script src="desktopsharing.js?v=2"></script><!-- desktop sharing -->
|
||||
<script src="data_channels.js?v=3"></script><!-- data channels -->
|
||||
<script src="app.js?v=7"></script><!-- application logic -->
|
||||
<script src="app.js?v=9"></script><!-- application logic -->
|
||||
<script src="commands.js?v=1"></script><!-- application logic -->
|
||||
<script src="chat.js?v=9"></script><!-- chat logic -->
|
||||
<script src="contact_list.js?v=1"></script><!-- contact list logic -->
|
||||
<script src="chat.js?v=10"></script><!-- chat logic -->
|
||||
<script src="contact_list.js?v=2"></script><!-- contact list logic -->
|
||||
<script src="util.js?v=6"></script><!-- utility functions -->
|
||||
<script src="etherpad.js?v=8"></script><!-- etherpad plugin -->
|
||||
<script src="prezi.js?v=4"></script><!-- prezi plugin -->
|
||||
<script src="etherpad.js?v=9"></script><!-- etherpad plugin -->
|
||||
<script src="prezi.js?v=5"></script><!-- prezi plugin -->
|
||||
<script src="smileys.js?v=2"></script><!-- smiley images -->
|
||||
<script src="replacement.js?v=6"></script><!-- link and smiley replacement -->
|
||||
<script src="moderatemuc.js?v=3"></script><!-- moderator plugin -->
|
||||
|
@ -43,17 +45,19 @@
|
|||
<script src="rtp_sts.js?v=1"></script><!-- RTP stats processing -->
|
||||
<script src="local_sts.js?v=1"></script><!-- Local stats processing -->
|
||||
<script src="videolayout.js?v=8"></script><!-- video ui -->
|
||||
<script src="toolbar.js?v=4"></script><!-- toolbar ui -->
|
||||
<script src="toolbar.js?v=5"></script><!-- toolbar ui -->
|
||||
<script src="toolbar_toggler.js?v=1"></script>
|
||||
<script src="canvas_util.js?v=1"></script><!-- canvas drawing utils -->
|
||||
<script src="audio_levels.js?v=1"></script><!-- audio levels plugin -->
|
||||
<script src="media_stream.js?v=1"></script><!-- media stream -->
|
||||
<script src="bottom_toolbar.js?v=1"></script><!-- media stream -->
|
||||
<script src="bottom_toolbar.js?v=2"></script><!-- media stream -->
|
||||
<script src="roomname_generator.js?v=1"></script><!-- generator for random room names -->
|
||||
<script src="keyboard_shortcut.js?v=1"></script>
|
||||
<script src="tracking.js?v=1"></script><!-- tracking -->
|
||||
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="css/font.css?v=3"/>
|
||||
<link rel="stylesheet" href="css/font.css?v=4"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=23"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=9" id="videolayout_default"/>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=10" id="videolayout_default"/>
|
||||
<link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
|
||||
<link rel="stylesheet" href="css/modaldialog.css?v=3">
|
||||
<link rel="stylesheet" href="css/popup_menu.css?v=2">
|
||||
|
@ -156,62 +160,62 @@
|
|||
<div style="position: relative;" id="header_container">
|
||||
<div id="header">
|
||||
<span id="toolbar">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Mute / Unmute" onclick='toggleAudio();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" shortcut="mutePopover" content="Mute / Unmute" onclick='toggleAudio();'>
|
||||
<i id="mute" class="icon-microphone"></i>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Start / stop camera" onclick='buttonClick("#video", "icon-camera icon-camera-disabled");toggleVideo();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" content="Start / stop camera" onclick='toggleVideo();'>
|
||||
<i id="video" class="icon-camera"></i>
|
||||
</a>
|
||||
<span id="recording" style="display: none">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Record" onclick='toggleRecording();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Record" onclick='toggleRecording();'>
|
||||
<i id="recordButton" class="icon-recEnable"></i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Lock / unlock room" onclick="Toolbar.openLockDialog();">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Lock / unlock room" onclick="Toolbar.openLockDialog();">
|
||||
<i id="lockIcon" class="icon-security"></i>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Invite others" onclick="Toolbar.openLinkDialog();">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Invite others" onclick="Toolbar.openLinkDialog();">
|
||||
<i class="icon-link"></i>
|
||||
</a>
|
||||
<div class="header_button_separator"></div>
|
||||
<span class="toolbar_span">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Open / close chat" onclick='BottomToolbar.toggleChat();'>
|
||||
<a class="button" data-toggle="popover" shortcut="toggleChatPopover" data-placement="bottom" content="Open / close chat" onclick='BottomToolbar.toggleChat();'>
|
||||
<i id="chatButton" class="icon-chat"></i>
|
||||
</a>
|
||||
<span id="unreadMessages"></span>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Share Prezi" onclick='Prezi.openPreziDialog();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Share Prezi" onclick='Prezi.openPreziDialog();'>
|
||||
<i class="icon-prezi"></i>
|
||||
</a>
|
||||
<span id="etherpadButton">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Shared document" onclick='Etherpad.toggleEtherpad(0);'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Shared document" onclick='Etherpad.toggleEtherpad(0);'>
|
||||
<i class="icon-share-doc"></i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<span id="desktopsharing" style="display: none">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Share screen" onclick="toggleScreenSharing();">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Share screen" onclick="toggleScreenSharing();">
|
||||
<i class="icon-share-desktop"></i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Enter / Exit Full Screen" onclick='buttonClick("#fullScreen", "icon-full-screen icon-exit-full-screen");Toolbar.toggleFullScreen();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Enter / Exit Full Screen" onclick='buttonClick("#fullScreen", "icon-full-screen icon-exit-full-screen");Toolbar.toggleFullScreen();'>
|
||||
<i id="fullScreen" class="icon-full-screen"></i>
|
||||
</a>
|
||||
<span id="sipCallButton">
|
||||
<div class="header_button_separator"></div>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Call SIP number" onclick='callSipButtonClicked();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Call SIP number" onclick='callSipButtonClicked();'>
|
||||
<i class="icon-telephone"></i></a>
|
||||
</span>
|
||||
<div class="header_button_separator"></div>
|
||||
<span id="hangup">
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" data-content="Hang Up" onclick='hangup();'>
|
||||
<a class="button" data-toggle="popover" data-placement="bottom" content="Hang Up" onclick='hangup();'>
|
||||
<i class="icon-hangup" style="color:#ff0000;font-size: 1.4em;"></i>
|
||||
</a>
|
||||
</span>
|
||||
|
@ -229,7 +233,7 @@
|
|||
</form>
|
||||
</div>
|
||||
<div id="reloadPresentation"><a onclick='Prezi.reloadPresentation();'><i title="Reload Prezi" class="fa fa-repeat fa-lg"></i></a></div>
|
||||
<div id="videospace" onmousemove="Toolbar.showToolbar();">
|
||||
<div id="videospace" onmousemove="ToolbarToggler.showToolbar();">
|
||||
<div id="largeVideoContainer" class="videocontainer">
|
||||
<div id="presentation"></div>
|
||||
<div id="etherpad"></div>
|
||||
|
@ -251,16 +255,19 @@
|
|||
</div>
|
||||
<span id="bottomToolbar">
|
||||
<span class="bottomToolbar_span">
|
||||
<a class="bottomToolbarButton" data-toggle="popover" data-placement="top" data-content="Open / close chat" onclick='BottomToolbar.toggleChat();'>
|
||||
<a class="bottomToolbarButton" data-container="body" data-toggle="popover" shortcut="toggleChatPopover" data-placement="top" content="Open / close chat" onclick='BottomToolbar.toggleChat();'>
|
||||
<i id="chatBottomButton" class="icon-chat-simple"></i>
|
||||
</a>
|
||||
<span id="unreadMessages"></span>
|
||||
</span>
|
||||
<span class="bottomToolbar_span">
|
||||
<a class="bottomToolbarButton" data-toggle="popover" data-placement="top" data-content="Open / close contact list" onclick='BottomToolbar.toggleContactList();'>
|
||||
<a class="bottomToolbarButton" data-container="body" data-toggle="popover" data-placement="top" data-container="body" id="contactlistpopover" content="Open / close contact list" onclick='BottomToolbar.toggleContactList();'>
|
||||
<i id="contactListButton" class="icon-contactList"></i>
|
||||
</a>
|
||||
<span id="unreadMessages"></span>
|
||||
</span>
|
||||
<span class="bottomToolbar_span">
|
||||
<a class="bottomToolbarButton" data-container="body" data-toggle="popover" shortcut="filmstripPopover" data-placement="top" content="Show / hide film strip" onclick='BottomToolbar.toggleFilmStrip()'>
|
||||
<i id="filmStripButton" class="icon-filmstrip"></i>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
var KeyboardShortcut = (function(my) {
|
||||
//maps keycode to character, id of popover for given function and function
|
||||
var shortcuts = {
|
||||
67: {
|
||||
character: "C",
|
||||
id: "toggleChatPopover",
|
||||
function: BottomToolbar.toggleChat
|
||||
},
|
||||
70: {
|
||||
character: "F",
|
||||
id: "filmstripPopover",
|
||||
function: BottomToolbar.toggleFilmStrip
|
||||
},
|
||||
77: {
|
||||
character: "M",
|
||||
id: "mutePopover",
|
||||
function: toggleAudio
|
||||
},
|
||||
84: {
|
||||
character: "T",
|
||||
function: function() {
|
||||
if(!isAudioMuted()) {
|
||||
toggleAudio();
|
||||
}
|
||||
}
|
||||
},
|
||||
86: {
|
||||
character: "V",
|
||||
id: "toggleVideoPopover",
|
||||
function: toggleVideo
|
||||
}
|
||||
};
|
||||
|
||||
window.onkeyup = function(e) {
|
||||
if($("#chatspace").css("display") === "none" ||
|
||||
!($("#usermsg").is(":focus") || $("#nickinput").is(":focus"))) {
|
||||
var keycode = e.which;
|
||||
if (typeof shortcuts[keycode] === "object") {
|
||||
shortcuts[keycode].function();
|
||||
} else if (keycode >= "1".charCodeAt(0) && keycode <= "9".charCodeAt(0)) {
|
||||
var remoteVideos = $(".videocontainer:not(#mixedstream)"),
|
||||
videoWanted = keycode - "0".charCodeAt(0);
|
||||
if (remoteVideos.length > videoWanted) {
|
||||
remoteVideos[videoWanted].click();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onkeydown = function(e) {
|
||||
if($("#chatspace").css("display") === "none") {
|
||||
if(e.which === "T".charCodeAt(0)) {
|
||||
if(isAudioMuted()) {
|
||||
toggleAudio();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id indicates the popover associated with the shortcut
|
||||
* @returns {string} the keyboard shortcut used for the id given
|
||||
*/
|
||||
my.getShortcut = function(id) {
|
||||
for(var keycode in shortcuts) {
|
||||
if(shortcuts.hasOwnProperty(keycode)) {
|
||||
if (shortcuts[keycode].id === id) {
|
||||
return " (" + shortcuts[keycode].character + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
return my;
|
||||
}(KeyboardShortcut || {}));
|
|
@ -42,6 +42,7 @@ function ColibriFocus(connection, bridgejid) {
|
|||
|
||||
this.bridgejid = bridgejid;
|
||||
this.peers = [];
|
||||
this.remoteStreams = [];
|
||||
this.confid = null;
|
||||
|
||||
/**
|
||||
|
@ -143,6 +144,7 @@ ColibriFocus.prototype.makeConference = function (peers) {
|
|||
event.peerjid = jid;
|
||||
}
|
||||
});
|
||||
self.remoteStreams.push(event.stream);
|
||||
$(document).trigger('remotestreamadded.jingle', [event, self.sid]);
|
||||
};
|
||||
this.peerconnection.onicecandidate = function (event) {
|
||||
|
@ -526,9 +528,11 @@ ColibriFocus.prototype.createdConference = function (result) {
|
|||
}
|
||||
}
|
||||
bridgeSDP.raw = bridgeSDP.session + bridgeSDP.media.join('');
|
||||
var bridgeDesc = new RTCSessionDescription({type: 'offer', sdp: bridgeSDP.raw});
|
||||
var simulcast = new Simulcast();
|
||||
var bridgeDesc = simulcast.transformBridgeDescription(bridgeDesc);
|
||||
|
||||
this.peerconnection.setRemoteDescription(
|
||||
new RTCSessionDescription({type: 'offer', sdp: bridgeSDP.raw}),
|
||||
this.peerconnection.setRemoteDescription(bridgeDesc,
|
||||
function () {
|
||||
console.log('setRemoteDescription success');
|
||||
self.peerconnection.createAnswer(
|
||||
|
@ -554,6 +558,24 @@ ColibriFocus.prototype.createdConference = function (result) {
|
|||
endpoint: self.myMucResource
|
||||
});
|
||||
|
||||
// signal (through COLIBRI) to the bridge
|
||||
// the SSRC groups of the participant
|
||||
// that plays the role of the focus
|
||||
var ssrc_group_lines = SDPUtil.find_lines(media, 'a=ssrc-group:');
|
||||
var idx = 0;
|
||||
ssrc_group_lines.forEach(function(line) {
|
||||
idx = line.indexOf(' ');
|
||||
var semantics = line.substr(0, idx).substr(13);
|
||||
var ssrcs = line.substr(14 + semantics.length).split(' ');
|
||||
if (ssrcs.length != 0) {
|
||||
elem.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
|
||||
ssrcs.forEach(function(ssrc) {
|
||||
elem.c('source', { ssrc: ssrc })
|
||||
.up();
|
||||
});
|
||||
elem.up();
|
||||
}
|
||||
});
|
||||
// FIXME: should reuse code from .toJingle
|
||||
for (var j = 0; j < mline.fmt.length; j++)
|
||||
{
|
||||
|
@ -647,6 +669,7 @@ ColibriFocus.prototype.initiate = function (peer, isInitiator) {
|
|||
sdp.removeMediaLines(i, 'a=rtcp-mux');
|
||||
}
|
||||
sdp.removeMediaLines(i, 'a=ssrc:');
|
||||
sdp.removeMediaLines(i, 'a=ssrc-group:');
|
||||
sdp.removeMediaLines(i, 'a=crypto:');
|
||||
sdp.removeMediaLines(i, 'a=candidate:');
|
||||
sdp.removeMediaLines(i, 'a=ice-options:google-ice');
|
||||
|
@ -656,14 +679,20 @@ ColibriFocus.prototype.initiate = function (peer, isInitiator) {
|
|||
sdp.removeMediaLines(i, 'a=setup:');
|
||||
|
||||
if (1) { //i > 0) { // not for audio FIXME: does not work as intended
|
||||
// re-add all remote a=ssrcs
|
||||
// re-add all remote a=ssrcs _and_ a=ssrc-group
|
||||
for (var jid in this.remotessrc) {
|
||||
if (jid == peer || !this.remotessrc[jid][i])
|
||||
continue;
|
||||
sdp.media[i] += this.remotessrc[jid][i];
|
||||
}
|
||||
// and local a=ssrc lines
|
||||
sdp.media[i] += SDPUtil.find_lines(localSDP.media[i], 'a=ssrc').join('\r\n') + '\r\n';
|
||||
|
||||
// add local a=ssrc-group: lines
|
||||
lines = SDPUtil.find_lines(localSDP.media[i], 'a=ssrc-group:');
|
||||
if (lines.length != 0)
|
||||
sdp.media[i] += lines.join('\r\n') + '\r\n';
|
||||
|
||||
// and local a=ssrc: lines
|
||||
sdp.media[i] += SDPUtil.find_lines(localSDP.media[i], 'a=ssrc:').join('\r\n') + '\r\n';
|
||||
}
|
||||
}
|
||||
sdp.raw = sdp.session + sdp.media.join('');
|
||||
|
@ -865,6 +894,24 @@ ColibriFocus.prototype.updateChannel = function (remoteSDP, participant) {
|
|||
expire: self.channelExpire
|
||||
});
|
||||
|
||||
// signal (throught COLIBRI) to the bridge the SSRC groups of this
|
||||
// participant
|
||||
var ssrc_group_lines = SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc-group:');
|
||||
var idx = 0;
|
||||
ssrc_group_lines.forEach(function(line) {
|
||||
idx = line.indexOf(' ');
|
||||
var semantics = line.substr(0, idx).substr(13);
|
||||
var ssrcs = line.substr(14 + semantics.length).split(' ');
|
||||
if (ssrcs.length != 0) {
|
||||
change.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
|
||||
ssrcs.forEach(function(ssrc) {
|
||||
change.c('source', { ssrc: ssrc })
|
||||
.up();
|
||||
});
|
||||
change.up();
|
||||
}
|
||||
});
|
||||
|
||||
var rtpmap = SDPUtil.find_lines(remoteSDP.media[channel], 'a=rtpmap:');
|
||||
rtpmap.forEach(function (val) {
|
||||
// TODO: too much copy-paste
|
||||
|
@ -1029,20 +1076,33 @@ ColibriFocus.prototype.setRemoteDescription = function (session, elem, desctype)
|
|||
if (!remoteSDP.media[channel])
|
||||
continue;
|
||||
|
||||
var lines = SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc-group:');
|
||||
if (lines.length != 0)
|
||||
// prepend ssrc-groups
|
||||
this.remotessrc[session.peerjid][channel] = lines.join('\r\n') + '\r\n';
|
||||
|
||||
if (SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:').length)
|
||||
{
|
||||
this.remotessrc[session.peerjid][channel] =
|
||||
if (!this.remotessrc[session.peerjid][channel])
|
||||
this.remotessrc[session.peerjid][channel] = '';
|
||||
|
||||
this.remotessrc[session.peerjid][channel] +=
|
||||
SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:')
|
||||
.join('\r\n') + '\r\n';
|
||||
}
|
||||
}
|
||||
|
||||
// ACT 4: add new a=ssrc lines to local remotedescription
|
||||
// ACT 4: add new a=ssrc and s=ssrc-group lines to local remotedescription
|
||||
for (channel = 0; channel < this.channels[participant].length; channel++) {
|
||||
//if (channel == 0) continue; FIXME: does not work as intended
|
||||
if (!remoteSDP.media[channel])
|
||||
continue;
|
||||
|
||||
var lines = SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc-group:');
|
||||
if (lines.length != 0)
|
||||
this.peerconnection.enqueueAddSsrc(
|
||||
channel, SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc-group:').join('\r\n') + '\r\n');
|
||||
|
||||
if (SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:').length) {
|
||||
this.peerconnection.enqueueAddSsrc(
|
||||
channel,
|
||||
|
@ -1312,6 +1372,9 @@ ColibriFocus.prototype.sendTerminate = function (session, reason, text) {
|
|||
|
||||
ColibriFocus.prototype.setRTCPTerminationStrategy = function (strategyFQN) {
|
||||
var self = this;
|
||||
|
||||
// TODO(gp) maybe move the RTCP termination strategy element under the
|
||||
// content or channel element.
|
||||
var strategyIQ = $iq({to: this.bridgejid, type: 'set'});
|
||||
strategyIQ.c('conference', {
|
||||
xmlns: 'http://jitsi.org/protocol/colibri',
|
||||
|
@ -1379,3 +1442,50 @@ ColibriFocus.prototype.setChannelLastN = function (channelLastN) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the default value of the channel simulcast layer attribute in this
|
||||
* conference and updates/patches the existing channels.
|
||||
*/
|
||||
ColibriFocus.prototype.setReceiveSimulcastLayer = function (receiveSimulcastLayer) {
|
||||
if (('number' === typeof(receiveSimulcastLayer))
|
||||
&& (this.receiveSimulcastLayer !== receiveSimulcastLayer))
|
||||
{
|
||||
// TODO(gp) be able to set the receiving simulcast layer on a per
|
||||
// sender basis.
|
||||
this.receiveSimulcastLayer = receiveSimulcastLayer;
|
||||
|
||||
// Update/patch the existing channels.
|
||||
var patch = $iq({ to: this.bridgejid, type: 'set' });
|
||||
|
||||
patch.c(
|
||||
'conference',
|
||||
{ xmlns: 'http://jitsi.org/protocol/colibri', id: this.confid });
|
||||
patch.c('content', { name: 'video' });
|
||||
patch.c(
|
||||
'channel',
|
||||
{
|
||||
id: $(this.mychannel[1 /* video */]).attr('id'),
|
||||
'receive-simulcast-layer': this.receiveSimulcastLayer
|
||||
});
|
||||
patch.up(); // end of channel
|
||||
for (var p = 0; p < this.channels.length; p++)
|
||||
{
|
||||
patch.c(
|
||||
'channel',
|
||||
{
|
||||
id: $(this.channels[p][1 /* video */]).attr('id'),
|
||||
'receive-simulcast-layer': this.receiveSimulcastLayer
|
||||
});
|
||||
patch.up(); // end of channel
|
||||
}
|
||||
this.connection.sendIQ(
|
||||
patch,
|
||||
function (res) {
|
||||
console.info('Set channel simulcast receive layer succeeded:', res);
|
||||
},
|
||||
function (err) {
|
||||
console.error('Set channel simulcast receive layer failed:', err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -128,7 +128,11 @@ dumpSDP = function(description) {
|
|||
if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) {
|
||||
TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() { return this.peerconnection.localDescription; });
|
||||
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() {
|
||||
var simulcast = new Simulcast();
|
||||
var publicLocalDescription = simulcast.makeLocalDescriptionPublic(this.peerconnection.localDescription);
|
||||
return publicLocalDescription;
|
||||
});
|
||||
TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() { return this.peerconnection.remoteDescription; });
|
||||
}
|
||||
|
||||
|
@ -149,6 +153,8 @@ TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
|
|||
|
||||
TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {
|
||||
var self = this;
|
||||
var simulcast = new Simulcast();
|
||||
description = simulcast.transformLocalDescription(description);
|
||||
this.trace('setLocalDescription', dumpSDP(description));
|
||||
this.peerconnection.setLocalDescription(description,
|
||||
function () {
|
||||
|
@ -169,6 +175,8 @@ TraceablePeerConnection.prototype.setLocalDescription = function (description, s
|
|||
|
||||
TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {
|
||||
var self = this;
|
||||
var simulcast = new Simulcast();
|
||||
description = simulcast.transformRemoteDescription(description);
|
||||
this.trace('setRemoteDescription', dumpSDP(description));
|
||||
this.peerconnection.setRemoteDescription(description,
|
||||
function () {
|
||||
|
@ -208,6 +216,16 @@ TraceablePeerConnection.prototype.addSource = function (elem) {
|
|||
$(elem).each(function (idx, content) {
|
||||
var name = $(content).attr('name');
|
||||
var lines = '';
|
||||
tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
|
||||
var semantics = this.getAttribute('semantics');
|
||||
var ssrcs = $(this).find('>source').map(function () {
|
||||
return this.getAttribute('ssrc');
|
||||
}).get();
|
||||
|
||||
if (ssrcs.length != 0) {
|
||||
lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
|
||||
}
|
||||
});
|
||||
tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
|
||||
tmp.each(function () {
|
||||
var ssrc = $(this).attr('ssrc');
|
||||
|
@ -254,6 +272,16 @@ TraceablePeerConnection.prototype.removeSource = function (elem) {
|
|||
$(elem).each(function (idx, content) {
|
||||
var name = $(content).attr('name');
|
||||
var lines = '';
|
||||
tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
|
||||
var semantics = this.getAttribute('semantics');
|
||||
var ssrcs = $(this).find('>source').map(function () {
|
||||
return this.getAttribute('ssrc');
|
||||
}).get();
|
||||
|
||||
if (ssrcs.length != 0) {
|
||||
lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
|
||||
}
|
||||
});
|
||||
tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
|
||||
tmp.each(function () {
|
||||
var ssrc = $(this).attr('ssrc');
|
||||
|
@ -413,6 +441,8 @@ TraceablePeerConnection.prototype.createAnswer = function (successCallback, fail
|
|||
this.trace('createAnswer', JSON.stringify(constraints, null, ' '));
|
||||
this.peerconnection.createAnswer(
|
||||
function (answer) {
|
||||
var simulcast = new Simulcast();
|
||||
answer = simulcast.transformAnswer(answer);
|
||||
self.trace('createAnswerOnSuccess', dumpSDP(answer));
|
||||
successCallback(answer);
|
||||
},
|
||||
|
@ -628,18 +658,43 @@ function getUserMediaWithConstraints(um, success_callback, failure_callback, res
|
|||
constraints.video.mandatory.minFrameRate = fps;
|
||||
}
|
||||
|
||||
var isFF = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
|
||||
try {
|
||||
RTC.getUserMedia(constraints,
|
||||
function (stream) {
|
||||
console.log('onUserMediaSuccess');
|
||||
success_callback(stream);
|
||||
},
|
||||
function (error) {
|
||||
console.warn('Failed to get access to local media. Error ', error);
|
||||
if(failure_callback) {
|
||||
failure_callback(error);
|
||||
}
|
||||
});
|
||||
if (config.enableSimulcast
|
||||
&& constraints.video
|
||||
&& constraints.video.chromeMediaSource !== 'screen'
|
||||
&& constraints.video.chromeMediaSource !== 'desktop'
|
||||
&& !isAndroid
|
||||
|
||||
// We currently do not support FF, as it doesn't have multistream support.
|
||||
&& !isFF) {
|
||||
var simulcast = new Simulcast();
|
||||
simulcast.getUserMedia(constraints, function (stream) {
|
||||
console.log('onUserMediaSuccess');
|
||||
success_callback(stream);
|
||||
},
|
||||
function (error) {
|
||||
console.warn('Failed to get access to local media. Error ', error);
|
||||
if (failure_callback) {
|
||||
failure_callback(error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
RTC.getUserMedia(constraints,
|
||||
function (stream) {
|
||||
console.log('onUserMediaSuccess');
|
||||
success_callback(stream);
|
||||
},
|
||||
function (error) {
|
||||
console.warn('Failed to get access to local media. Error ', error);
|
||||
if (failure_callback) {
|
||||
failure_callback(error);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('GUM failed: ', e);
|
||||
if(failure_callback) {
|
||||
|
|
|
@ -31,6 +31,15 @@ SDP.prototype.getMediaSsrcMap = function() {
|
|||
}
|
||||
channel.ssrcs[linessrc].lines.push(line);
|
||||
});
|
||||
tmp = SDPUtil.find_lines(self.media[channelNum], 'a=ssrc-group:');
|
||||
tmp.forEach(function(line){
|
||||
var semantics = line.substr(0, idx).substr(13);
|
||||
var ssrcs = line.substr(14 + semantics.length).split(' ');
|
||||
if (ssrcs.length != 0) {
|
||||
var ssrcGroup = new ChannelSsrcGroup(semantics, ssrcs);
|
||||
channel.ssrcGroups.push(ssrcGroup);
|
||||
}
|
||||
});
|
||||
}
|
||||
return media_ssrcs;
|
||||
}
|
||||
|
@ -56,6 +65,32 @@ SDP.prototype.containsSSRC = function(ssrc) {
|
|||
* @param otherSdp the other SDP to check ssrc with.
|
||||
*/
|
||||
SDP.prototype.getNewMedia = function(otherSdp) {
|
||||
|
||||
// this could be useful in Array.prototype.
|
||||
function arrayEquals(array) {
|
||||
// if the other array is a falsy value, return
|
||||
if (!array)
|
||||
return false;
|
||||
|
||||
// compare lengths - can save a lot of time
|
||||
if (this.length != array.length)
|
||||
return false;
|
||||
|
||||
for (var i = 0, l=this.length; i < l; i++) {
|
||||
// Check if we have nested arrays
|
||||
if (this[i] instanceof Array && array[i] instanceof Array) {
|
||||
// recurse into the nested arrays
|
||||
if (!this[i].equals(array[i]))
|
||||
return false;
|
||||
}
|
||||
else if (this[i] != array[i]) {
|
||||
// Warning - two different object instances will never be equal: {x:20} != {x:20}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
var myMedia = this.getMediaSsrcMap();
|
||||
var othersMedia = otherSdp.getMediaSsrcMap();
|
||||
var newMedia = {};
|
||||
|
@ -77,6 +112,32 @@ SDP.prototype.getNewMedia = function(otherSdp) {
|
|||
newMedia[channelNum].ssrcs[ssrc] = othersChannel.ssrcs[ssrc];
|
||||
}
|
||||
})
|
||||
|
||||
// Look for new ssrc groups across the channels
|
||||
othersChannel.ssrcGroups.forEach(function(otherSsrcGroup){
|
||||
|
||||
// try to match the other ssrc-group with an ssrc-group of ours
|
||||
var matched = false;
|
||||
for (var i = 0; i < myChannel.ssrcGroups.length; i++) {
|
||||
var mySsrcGroup = myChannel.ssrcGroups[i];
|
||||
if (otherSsrcGroup.semantics == mySsrcGroup
|
||||
&& arrayEquals.apply(otherSsrcGroup.ssrcs, [mySsrcGroup.ssrcs])) {
|
||||
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
// Allocate channel if we've found an ssrc-group that doesn't
|
||||
// exist in our channel
|
||||
|
||||
if(!newMedia[channelNum]){
|
||||
newMedia[channelNum] = new MediaChannel(othersChannel.chNumber, othersChannel.mediaType);
|
||||
}
|
||||
newMedia[channelNum].ssrcGroups.push(otherSsrcGroup);
|
||||
}
|
||||
});
|
||||
});
|
||||
return newMedia;
|
||||
}
|
||||
|
@ -241,6 +302,22 @@ SDP.prototype.toJingle = function (elem, thecreator) {
|
|||
tmp.xmlns = 'http://estos.de/ns/ssrc';
|
||||
tmp.ssrc = ssrc;
|
||||
elem.c('ssrc', tmp).up(); // ssrc is part of description
|
||||
|
||||
// XEP-0339 handle ssrc-group attributes
|
||||
var ssrc_group_lines = SDPUtil.find_lines(this.media[i], 'a=ssrc-group:');
|
||||
ssrc_group_lines.forEach(function(line) {
|
||||
idx = line.indexOf(' ');
|
||||
var semantics = line.substr(0, idx).substr(13);
|
||||
var ssrcs = line.substr(14 + semantics.length).split(' ');
|
||||
if (ssrcs.length != 0) {
|
||||
elem.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
|
||||
ssrcs.forEach(function(ssrc) {
|
||||
elem.c('source', { ssrc: ssrc })
|
||||
.up();
|
||||
});
|
||||
elem.up();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (SDPUtil.find_line(this.media[i], 'a=rtcp-mux')) {
|
||||
|
@ -578,6 +655,18 @@ SDP.prototype.jingle2media = function (content) {
|
|||
media += SDPUtil.candidateFromJingle(this);
|
||||
});
|
||||
|
||||
// XEP-0339 handle ssrc-group attributes
|
||||
tmp = content.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
|
||||
var semantics = this.getAttribute('semantics');
|
||||
var ssrcs = $(this).find('>source').map(function() {
|
||||
return this.getAttribute('ssrc');
|
||||
}).get();
|
||||
|
||||
if (ssrcs.length != 0) {
|
||||
media += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
|
||||
}
|
||||
});
|
||||
|
||||
tmp = content.find('description>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
|
||||
tmp.each(function () {
|
||||
var ssrc = this.getAttribute('ssrc');
|
||||
|
|
|
@ -15,6 +15,17 @@ function ChannelSsrc(ssrc, type) {
|
|||
this.lines = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Class holds a=ssrc-group: lines
|
||||
* @param semantics
|
||||
* @param ssrcs
|
||||
* @constructor
|
||||
*/
|
||||
function ChannelSsrcGroup(semantics, ssrcs, line) {
|
||||
this.semantics = semantics;
|
||||
this.ssrcs = ssrcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class represents media channel. Is a container for ChannelSsrc, holds channel idx and media type.
|
||||
* @param channelNumber channel idx in SDP media array.
|
||||
|
@ -36,6 +47,12 @@ function MediaChannel(channelNumber, mediaType) {
|
|||
* The maps of ssrc numbers to ChannelSsrc objects.
|
||||
*/
|
||||
this.ssrcs = {};
|
||||
|
||||
/**
|
||||
* The array of ChannelSsrcGroup objects.
|
||||
* @type {Array}
|
||||
*/
|
||||
this.ssrcGroups = [];
|
||||
}
|
||||
|
||||
SDPUtil = {
|
||||
|
|
|
@ -119,6 +119,8 @@ JingleSession.prototype.accept = function () {
|
|||
// FIXME: change any inactive to sendrecv or whatever they were originally
|
||||
pranswer.sdp = pranswer.sdp.replace('a=inactive', 'a=sendrecv');
|
||||
}
|
||||
var simulcast = new Simulcast();
|
||||
pranswer = simulcast.makeLocalDescriptionPublic(pranswer);
|
||||
var prsdp = new SDP(pranswer.sdp);
|
||||
var accept = $iq({to: this.peerjid,
|
||||
type: 'set'})
|
||||
|
@ -565,7 +567,10 @@ JingleSession.prototype.createdAnswer = function (sdp, provisional) {
|
|||
initiator: this.initiator,
|
||||
responder: this.responder,
|
||||
sid: this.sid });
|
||||
this.localSDP.toJingle(accept, this.initiator == this.me ? 'initiator' : 'responder');
|
||||
var simulcast = new Simulcast();
|
||||
var publicLocalDesc = simulcast.makeLocalDescriptionPublic(sdp);
|
||||
var publicLocalSDP = new SDP(publicLocalDesc.sdp);
|
||||
publicLocalSDP.toJingle(accept, this.initiator == this.me ? 'initiator' : 'responder');
|
||||
this.connection.sendIQ(accept,
|
||||
function () {
|
||||
var ack = {};
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Strophe logger implementation. Logs from level WARN and above.
|
||||
*/
|
||||
Strophe.log = function (level, msg) {
|
||||
switch(level) {
|
||||
case Strophe.LogLevel.WARN:
|
||||
console.warn("Strophe: "+msg);
|
||||
break;
|
||||
case Strophe.LogLevel.ERROR:
|
||||
case Strophe.LogLevel.FATAL:
|
||||
console.error("Strophe: "+msg);
|
||||
break;
|
||||
}
|
||||
};
|
4
prezi.js
|
@ -22,7 +22,7 @@ var Prezi = (function (my) {
|
|||
VideoLayout.setLargeVideoVisible(false);
|
||||
$('#presentation>iframe').fadeIn(300, function() {
|
||||
$('#presentation>iframe').css({opacity:'1'});
|
||||
Toolbar.dockToolbar(true);
|
||||
ToolbarToggler.dockToolbar(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ var Prezi = (function (my) {
|
|||
$('#reloadPresentation').css({display:'none'});
|
||||
$('#largeVideo').fadeIn(300, function() {
|
||||
VideoLayout.setLargeVideoVisible(true);
|
||||
Toolbar.dockToolbar(false);
|
||||
ToolbarToggler.dockToolbar(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ var RoomNameGenerator = function(my) {
|
|||
*/
|
||||
function generateWord()
|
||||
{
|
||||
return words[( Math.round(((new Date().getTime() / 1000) +Math.random()*1000) % 1008))];
|
||||
return words[Math.floor(Math.random() * words.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,669 @@
|
|||
/*jslint plusplus: true */
|
||||
/*jslint nomen: true*/
|
||||
|
||||
/**
|
||||
* Created by gp on 11/08/14.
|
||||
*/
|
||||
function Simulcast() {
|
||||
"use strict";
|
||||
|
||||
// TODO(gp) split the Simulcast class in two classes : NativeSimulcast and ClassicSimulcast.
|
||||
this.debugLvl = 1;
|
||||
}
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
// global state for all transformers.
|
||||
var localExplosionMap = {}, localVideoSourceCache, emptyCompoundIndex,
|
||||
remoteMaps = {
|
||||
msid2Quality: {},
|
||||
ssrc2Msid: {},
|
||||
receivingVideoStreams: {}
|
||||
}, localMaps = {
|
||||
msids: [],
|
||||
msid2ssrc: {}
|
||||
};
|
||||
|
||||
Simulcast.prototype._generateGuid = (function () {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
return function () {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
};
|
||||
}());
|
||||
|
||||
Simulcast.prototype._cacheVideoSources = function (lines) {
|
||||
localVideoSourceCache = this._getVideoSources(lines);
|
||||
};
|
||||
|
||||
Simulcast.prototype._restoreVideoSources = function (lines) {
|
||||
this._replaceVideoSources(lines, localVideoSourceCache);
|
||||
};
|
||||
|
||||
Simulcast.prototype._replaceVideoSources = function (lines, videoSources) {
|
||||
|
||||
var i, inVideo = false, index = -1, howMany = 0;
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Replacing video sources...');
|
||||
}
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (inVideo && lines[i].substring(0, 'm='.length) === 'm=') {
|
||||
// Out of video.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inVideo && lines[i].substring(0, 'm=video '.length) === 'm=video ') {
|
||||
// In video.
|
||||
inVideo = true;
|
||||
}
|
||||
|
||||
if (inVideo && (lines[i].substring(0, 'a=ssrc:'.length) === 'a=ssrc:'
|
||||
|| lines[i].substring(0, 'a=ssrc-group:'.length) === 'a=ssrc-group:')) {
|
||||
|
||||
if (index === -1) {
|
||||
index = i;
|
||||
}
|
||||
|
||||
howMany++;
|
||||
}
|
||||
}
|
||||
|
||||
// efficiency baby ;)
|
||||
lines.splice.apply(lines,
|
||||
[index, howMany].concat(videoSources));
|
||||
|
||||
};
|
||||
|
||||
Simulcast.prototype._getVideoSources = function (lines) {
|
||||
var i, inVideo = false, sb = [];
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Getting video sources...');
|
||||
}
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (inVideo && lines[i].substring(0, 'm='.length) === 'm=') {
|
||||
// Out of video.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inVideo && lines[i].substring(0, 'm=video '.length) === 'm=video ') {
|
||||
// In video.
|
||||
inVideo = true;
|
||||
}
|
||||
|
||||
if (inVideo && lines[i].substring(0, 'a=ssrc:'.length) === 'a=ssrc:') {
|
||||
// In SSRC.
|
||||
sb.push(lines[i]);
|
||||
}
|
||||
|
||||
if (inVideo && lines[i].substring(0, 'a=ssrc-group:'.length) === 'a=ssrc-group:') {
|
||||
sb.push(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
};
|
||||
|
||||
Simulcast.prototype._parseMedia = function (lines, mediatypes) {
|
||||
var i, res = [], type, cur_media, idx, ssrcs, cur_ssrc, ssrc,
|
||||
ssrc_attribute, group, semantics, skip;
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Parsing media sources...');
|
||||
}
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (lines[i].substring(0, 'm='.length) === 'm=') {
|
||||
|
||||
type = lines[i]
|
||||
.substr('m='.length, lines[i].indexOf(' ') - 'm='.length);
|
||||
skip = mediatypes !== undefined && mediatypes.indexOf(type) === -1;
|
||||
|
||||
if (!skip) {
|
||||
cur_media = {
|
||||
'type': type,
|
||||
'sources': {},
|
||||
'groups': []
|
||||
};
|
||||
|
||||
res.push(cur_media);
|
||||
}
|
||||
|
||||
} else if (!skip && lines[i].substring(0, 'a=ssrc:'.length) === 'a=ssrc:') {
|
||||
|
||||
idx = lines[i].indexOf(' ');
|
||||
ssrc = lines[i].substring('a=ssrc:'.length, idx);
|
||||
if (cur_media.sources[ssrc] === undefined) {
|
||||
cur_ssrc = {'ssrc': ssrc};
|
||||
cur_media.sources[ssrc] = cur_ssrc;
|
||||
}
|
||||
|
||||
ssrc_attribute = lines[i].substr(idx + 1).split(':', 2)[0];
|
||||
cur_ssrc[ssrc_attribute] = lines[i].substr(idx + 1).split(':', 2)[1];
|
||||
|
||||
if (cur_media.base === undefined) {
|
||||
cur_media.base = cur_ssrc;
|
||||
}
|
||||
|
||||
} else if (!skip && lines[i].substring(0, 'a=ssrc-group:'.length) === 'a=ssrc-group:') {
|
||||
idx = lines[i].indexOf(' ');
|
||||
semantics = lines[i].substr(0, idx).substr('a=ssrc-group:'.length);
|
||||
ssrcs = lines[i].substr(idx).trim().split(' ');
|
||||
group = {
|
||||
'semantics': semantics,
|
||||
'ssrcs': ssrcs
|
||||
};
|
||||
cur_media.groups.push(group);
|
||||
} else if (!skip && (lines[i].substring(0, 'a=sendrecv'.length) === 'a=sendrecv' ||
|
||||
lines[i].substring(0, 'a=recvonly'.length) === 'a=recvonly' ||
|
||||
lines[i].substring(0, 'a=sendonly'.length) === 'a=sendonly' ||
|
||||
lines[i].substring(0, 'a=inactive'.length) === 'a=inactive')) {
|
||||
|
||||
cur_media.direction = lines[i].substring('a='.length, 8);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a random integer between min (included) and max (excluded)
|
||||
// Using Math.round() will give you a non-uniform distribution!
|
||||
Simulcast.prototype._generateRandomSSRC = function () {
|
||||
var min = 0, max = 0xffffffff;
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
};
|
||||
|
||||
function CompoundIndex(obj) {
|
||||
if (obj !== undefined) {
|
||||
this.row = obj.row;
|
||||
this.column = obj.column;
|
||||
}
|
||||
}
|
||||
|
||||
emptyCompoundIndex = new CompoundIndex();
|
||||
|
||||
Simulcast.prototype._indexOfArray = function (needle, haystack, start) {
|
||||
var length = haystack.length, idx, i;
|
||||
|
||||
if (!start) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
for (i = start; i < length; i++) {
|
||||
idx = haystack[i].indexOf(needle);
|
||||
if (idx !== -1) {
|
||||
return new CompoundIndex({row: i, column: idx});
|
||||
}
|
||||
}
|
||||
return emptyCompoundIndex;
|
||||
};
|
||||
|
||||
Simulcast.prototype._removeSimulcastGroup = function (lines) {
|
||||
var i;
|
||||
|
||||
for (i = lines.length - 1; i >= 0; i--) {
|
||||
if (lines[i].indexOf('a=ssrc-group:SIM') !== -1) {
|
||||
lines.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Simulcast.prototype._explodeLocalSimulcastSources = function (lines) {
|
||||
var sb, msid, sid, tid, videoSources, self;
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Exploding local video sources...');
|
||||
}
|
||||
|
||||
videoSources = this._parseMedia(lines, ['video'])[0];
|
||||
|
||||
self = this;
|
||||
if (videoSources.groups && videoSources.groups.length !== 0) {
|
||||
videoSources.groups.forEach(function (group) {
|
||||
if (group.semantics === 'SIM') {
|
||||
group.ssrcs.forEach(function (ssrc) {
|
||||
|
||||
// Get the msid for this ssrc..
|
||||
if (localExplosionMap[ssrc]) {
|
||||
// .. either from the explosion map..
|
||||
msid = localExplosionMap[ssrc];
|
||||
} else {
|
||||
// .. or generate a new one (msid).
|
||||
sid = videoSources.sources[ssrc].msid
|
||||
.substring(0, videoSources.sources[ssrc].msid.indexOf(' '));
|
||||
|
||||
tid = self._generateGuid();
|
||||
msid = [sid, tid].join(' ');
|
||||
localExplosionMap[ssrc] = msid;
|
||||
}
|
||||
|
||||
// Assign it to the source object.
|
||||
videoSources.sources[ssrc].msid = msid;
|
||||
|
||||
// TODO(gp) Change the msid of associated sources.
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sb = this._compileVideoSources(videoSources);
|
||||
|
||||
this._replaceVideoSources(lines, sb);
|
||||
};
|
||||
|
||||
Simulcast.prototype._groupLocalVideoSources = function (lines) {
|
||||
var sb, videoSources, ssrcs = [], ssrc;
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Grouping local video sources...');
|
||||
}
|
||||
|
||||
videoSources = this._parseMedia(lines, ['video'])[0];
|
||||
|
||||
for (ssrc in videoSources.sources) {
|
||||
// jitsi-meet destroys/creates streams at various places causing
|
||||
// the original local stream ids to change. The only thing that
|
||||
// remains unchanged is the trackid.
|
||||
localMaps.msid2ssrc[videoSources.sources[ssrc].msid.split(' ')[1]] = ssrc;
|
||||
}
|
||||
|
||||
// TODO(gp) add only "free" sources.
|
||||
localMaps.msids.forEach(function (msid) {
|
||||
ssrcs.push(localMaps.msid2ssrc[msid]);
|
||||
});
|
||||
|
||||
if (!videoSources.groups) {
|
||||
videoSources.groups = [];
|
||||
}
|
||||
|
||||
videoSources.groups.push({
|
||||
'semantics': 'SIM',
|
||||
'ssrcs': ssrcs
|
||||
});
|
||||
|
||||
sb = this._compileVideoSources(videoSources);
|
||||
|
||||
this._replaceVideoSources(lines, sb);
|
||||
};
|
||||
|
||||
Simulcast.prototype._appendSimulcastGroup = function (lines) {
|
||||
var videoSources, ssrcGroup, simSSRC, numOfSubs = 3, i, sb, msid;
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Appending simulcast group...');
|
||||
}
|
||||
|
||||
// Get the primary SSRC information.
|
||||
videoSources = this._parseMedia(lines, ['video'])[0];
|
||||
|
||||
// Start building the SIM SSRC group.
|
||||
ssrcGroup = ['a=ssrc-group:SIM'];
|
||||
|
||||
// The video source buffer.
|
||||
sb = [];
|
||||
|
||||
// Create the simulcast sub-streams.
|
||||
for (i = 0; i < numOfSubs; i++) {
|
||||
// TODO(gp) prevent SSRC collision.
|
||||
simSSRC = this._generateRandomSSRC();
|
||||
ssrcGroup.push(simSSRC);
|
||||
|
||||
sb.splice.apply(sb, [sb.length, 0].concat(
|
||||
[["a=ssrc:", simSSRC, " cname:", videoSources.base.cname].join(''),
|
||||
["a=ssrc:", simSSRC, " msid:", videoSources.base.msid].join('')]
|
||||
));
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info(['Generated substream ', i, ' with SSRC ', simSSRC, '.'].join(''));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the group sim layers.
|
||||
sb.splice(0, 0, ssrcGroup.join(' '))
|
||||
|
||||
this._replaceVideoSources(lines, sb);
|
||||
};
|
||||
|
||||
// Does the actual patching.
|
||||
Simulcast.prototype._ensureSimulcastGroup = function (lines) {
|
||||
if (this.debugLvl) {
|
||||
console.info('Ensuring simulcast group...');
|
||||
}
|
||||
|
||||
if (this._indexOfArray('a=ssrc-group:SIM', lines) === emptyCompoundIndex) {
|
||||
this._appendSimulcastGroup(lines);
|
||||
this._cacheVideoSources(lines);
|
||||
} else {
|
||||
// verify that the ssrcs participating in the SIM group are present
|
||||
// in the SDP (needed for presence).
|
||||
this._restoreVideoSources(lines);
|
||||
}
|
||||
};
|
||||
|
||||
Simulcast.prototype._ensureGoogConference = function (lines) {
|
||||
var sb;
|
||||
if (this.debugLvl) {
|
||||
console.info('Ensuring x-google-conference flag...')
|
||||
}
|
||||
|
||||
if (this._indexOfArray('a=x-google-flag:conference', lines) === emptyCompoundIndex) {
|
||||
// Add the google conference flag
|
||||
sb = this._getVideoSources(lines);
|
||||
sb = ['a=x-google-flag:conference'].concat(sb);
|
||||
this._replaceVideoSources(lines, sb);
|
||||
}
|
||||
};
|
||||
|
||||
Simulcast.prototype._compileVideoSources = function (videoSources) {
|
||||
var sb = [], ssrc, addedSSRCs = [];
|
||||
|
||||
if (this.debugLvl) {
|
||||
console.info('Compiling video sources...');
|
||||
}
|
||||
|
||||
// Add the groups
|
||||
if (videoSources.groups && videoSources.groups.length !== 0) {
|
||||
videoSources.groups.forEach(function (group) {
|
||||
if (group.ssrcs && group.ssrcs.length !== 0) {
|
||||
sb.push([['a=ssrc-group:', group.semantics].join(''), group.ssrcs.join(' ')].join(' '));
|
||||
|
||||
// if (group.semantics !== 'SIM') {
|
||||
group.ssrcs.forEach(function (ssrc) {
|
||||
addedSSRCs.push(ssrc);
|
||||
sb.splice.apply(sb, [sb.length, 0].concat([
|
||||
["a=ssrc:", ssrc, " cname:", videoSources.sources[ssrc].cname].join(''),
|
||||
["a=ssrc:", ssrc, " msid:", videoSources.sources[ssrc].msid].join('')]));
|
||||
});
|
||||
//}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Then add any free sources.
|
||||
if (videoSources.sources) {
|
||||
for (ssrc in videoSources.sources) {
|
||||
if (addedSSRCs.indexOf(ssrc) === -1) {
|
||||
sb.splice.apply(sb, [sb.length, 0].concat([
|
||||
["a=ssrc:", ssrc, " cname:", videoSources.sources[ssrc].cname].join(''),
|
||||
["a=ssrc:", ssrc, " msid:", videoSources.sources[ssrc].msid].join('')]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
};
|
||||
|
||||
Simulcast.prototype.transformAnswer = function (desc) {
|
||||
if (config.enableSimulcast && config.useNativeSimulcast) {
|
||||
|
||||
var sb = desc.sdp.split('\r\n');
|
||||
|
||||
// Even if we have enabled native simulcasting previously
|
||||
// (with a call to SLD with an appropriate SDP, for example),
|
||||
// createAnswer seems to consistently generate incomplete SDP
|
||||
// with missing SSRCS.
|
||||
//
|
||||
// So, subsequent calls to SLD will have missing SSRCS and presence
|
||||
// won't have the complete list of SRCs.
|
||||
this._ensureSimulcastGroup(sb);
|
||||
|
||||
desc = new RTCSessionDescription({
|
||||
type: desc.type,
|
||||
sdp: sb.join('\r\n')
|
||||
});
|
||||
|
||||
if (this.debugLvl && this.debugLvl > 1) {
|
||||
console.info('Transformed answer');
|
||||
console.info(desc.sdp);
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
};
|
||||
|
||||
Simulcast.prototype.makeLocalDescriptionPublic = function (desc) {
|
||||
var sb;
|
||||
|
||||
if (!desc || desc == null)
|
||||
return desc;
|
||||
|
||||
if (config.enableSimulcast) {
|
||||
|
||||
if (config.useNativeSimulcast) {
|
||||
sb = desc.sdp.split('\r\n');
|
||||
|
||||
this._explodeLocalSimulcastSources(sb);
|
||||
|
||||
desc = new RTCSessionDescription({
|
||||
type: desc.type,
|
||||
sdp: sb.join('\r\n')
|
||||
});
|
||||
|
||||
if (this.debugLvl && this.debugLvl > 1) {
|
||||
console.info('Exploded local video sources');
|
||||
console.info(desc.sdp);
|
||||
}
|
||||
} else {
|
||||
sb = desc.sdp.split('\r\n');
|
||||
|
||||
this._groupLocalVideoSources(sb);
|
||||
|
||||
desc = new RTCSessionDescription({
|
||||
type: desc.type,
|
||||
sdp: sb.join('\r\n')
|
||||
});
|
||||
|
||||
if (this.debugLvl && this.debugLvl > 1) {
|
||||
console.info('Grouped local video sources');
|
||||
console.info(desc.sdp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
};
|
||||
|
||||
Simulcast.prototype._ensureOrder = function (lines) {
|
||||
var videoSources, sb;
|
||||
|
||||
videoSources = this._parseMedia(lines, ['video'])[0];
|
||||
sb = this._compileVideoSources(videoSources);
|
||||
|
||||
this._replaceVideoSources(lines, sb);
|
||||
};
|
||||
|
||||
Simulcast.prototype.transformBridgeDescription = function (desc) {
|
||||
if (config.enableSimulcast && config.useNativeSimulcast) {
|
||||
|
||||
var sb = desc.sdp.split('\r\n');
|
||||
|
||||
this._ensureGoogConference(sb);
|
||||
|
||||
desc = new RTCSessionDescription({
|
||||
type: desc.type,
|
||||
sdp: sb.join('\r\n')
|
||||
});
|
||||
|
||||
if (this.debugLvl && this.debugLvl > 1) {
|
||||
console.info('Transformed bridge description');
|
||||
console.info(desc.sdp);
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
};
|
||||
|
||||
Simulcast.prototype._updateRemoteMaps = function (lines) {
|
||||
var remoteVideoSources = this._parseMedia(lines, ['video'])[0], videoSource, quality;
|
||||
|
||||
if (remoteVideoSources.groups && remoteVideoSources.groups.length !== 0) {
|
||||
remoteVideoSources.groups.forEach(function (group) {
|
||||
if (group.semantics === 'SIM' && group.ssrcs && group.ssrcs.length !== 0) {
|
||||
quality = 0;
|
||||
group.ssrcs.forEach(function (ssrc) {
|
||||
videoSource = remoteVideoSources.sources[ssrc];
|
||||
remoteMaps.msid2Quality[videoSource.msid] = quality++;
|
||||
remoteMaps.ssrc2Msid[videoSource.ssrc] = videoSource.msid;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Simulcast.prototype.transformLocalDescription = function (desc) {
|
||||
if (config.enableSimulcast && !config.useNativeSimulcast) {
|
||||
|
||||
var sb = desc.sdp.split('\r\n');
|
||||
|
||||
this._removeSimulcastGroup(sb);
|
||||
|
||||
desc = new RTCSessionDescription({
|
||||
type: desc.type,
|
||||
sdp: sb.join('\r\n')
|
||||
});
|
||||
|
||||
if (this.debugLvl && this.debugLvl > 1) {
|
||||
console.info('Transformed local description');
|
||||
console.info(desc.sdp);
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
};
|
||||
|
||||
Simulcast.prototype.transformRemoteDescription = function (desc) {
|
||||
if (config.enableSimulcast) {
|
||||
|
||||
var sb = desc.sdp.split('\r\n');
|
||||
|
||||
this._updateRemoteMaps(sb);
|
||||
this._removeSimulcastGroup(sb); // NOTE(gp) this needs to be called after updateRemoteMaps!
|
||||
this._ensureGoogConference(sb);
|
||||
|
||||
desc = new RTCSessionDescription({
|
||||
type: desc.type,
|
||||
sdp: sb.join('\r\n')
|
||||
});
|
||||
|
||||
if (this.debugLvl && this.debugLvl > 1) {
|
||||
console.info('Transformed remote description');
|
||||
console.info(desc.sdp);
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
};
|
||||
|
||||
Simulcast.prototype.setReceivingVideoStream = function (ssrc) {
|
||||
var receivingTrack = remoteMaps.ssrc2Msid[ssrc],
|
||||
msidParts = receivingTrack.split(' ');
|
||||
|
||||
remoteMaps.receivingVideoStreams[msidParts[0]] = msidParts[1];
|
||||
};
|
||||
|
||||
Simulcast.prototype.getReceivingVideoStream = function (stream) {
|
||||
var tracks, track, i, electedTrack, msid, quality = 1, receivingTrackId;
|
||||
|
||||
if (config.enableSimulcast) {
|
||||
|
||||
if (remoteMaps.receivingVideoStreams[stream.id])
|
||||
{
|
||||
receivingTrackId = remoteMaps.receivingVideoStreams[stream.id];
|
||||
tracks = stream.getVideoTracks();
|
||||
for (i = 0; i < tracks.length; i++) {
|
||||
if (receivingTrackId === tracks[i].id) {
|
||||
electedTrack = tracks[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!electedTrack) {
|
||||
tracks = stream.getVideoTracks();
|
||||
for (i = 0; i < tracks.length; i++) {
|
||||
track = tracks[i];
|
||||
msid = [stream.id, track.id].join(' ');
|
||||
if (remoteMaps.msid2Quality[msid] === quality) {
|
||||
electedTrack = track;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (electedTrack)
|
||||
? new webkitMediaStream([electedTrack])
|
||||
: stream;
|
||||
};
|
||||
|
||||
Simulcast.prototype.getUserMedia = function (constraints, success, err) {
|
||||
|
||||
// TODO(gp) what if we request a resolution not supported by the hardware?
|
||||
// TODO(gp) make the lq stream configurable; although this wouldn't work with native simulcast
|
||||
var lqConstraints = {
|
||||
audio: false,
|
||||
video: {
|
||||
mandatory: {
|
||||
maxWidth: 320,
|
||||
maxHeight: 180
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (config.enableSimulcast && !config.useNativeSimulcast) {
|
||||
|
||||
// NOTE(gp) if we request the lq stream first webkitGetUserMedia fails randomly. Tested with Chrome 37.
|
||||
|
||||
navigator.webkitGetUserMedia(constraints, function (hqStream) {
|
||||
|
||||
// reset local maps.
|
||||
localMaps.msids = [];
|
||||
localMaps.msid2ssrc = {};
|
||||
|
||||
// add hq trackid to local map
|
||||
localMaps.msids.push(hqStream.getVideoTracks()[0].id);
|
||||
|
||||
navigator.webkitGetUserMedia(lqConstraints, function (lqStream) {
|
||||
|
||||
// add lq trackid to local map
|
||||
localMaps.msids.push(lqStream.getVideoTracks()[0].id);
|
||||
|
||||
hqStream.addTrack(lqStream.getVideoTracks()[0]);
|
||||
success(hqStream);
|
||||
}, err);
|
||||
}, err);
|
||||
} else {
|
||||
|
||||
// There's nothing special to do for native simulcast, so just do a normal GUM.
|
||||
|
||||
navigator.webkitGetUserMedia(constraints, function (hqStream) {
|
||||
|
||||
// reset local maps.
|
||||
localMaps.msids = [];
|
||||
localMaps.msid2ssrc = {};
|
||||
|
||||
// add hq stream to local map
|
||||
localMaps.msids.push(hqStream.getVideoTracks()[0].id);
|
||||
|
||||
success(hqStream);
|
||||
}, err);
|
||||
}
|
||||
};
|
||||
|
||||
Simulcast.prototype.getRemoteVideoStreamIdBySSRC = function (primarySSRC) {
|
||||
return remoteMaps.ssrc2Msid[primarySSRC];
|
||||
};
|
||||
|
||||
Simulcast.prototype.parseMedia = function (desc, mediatypes) {
|
||||
var lines = desc.sdp.split('\r\n');
|
||||
return this._parseMedia(lines, mediatypes);
|
||||
};
|
||||
}());
|
40
smileys.js
|
@ -1,45 +1,45 @@
|
|||
var smiley1 = "data:image/gif;base64,R0lGODlhGAAaANU/ALW3uYWHicLExkRERurr7PaQcv3VxHR1d2VmafiojFZXWdna2/vKtzw7PZaYm+Pk5f39/SonKO0fJfJrTvX29vLy89PU1qKkpqmrrfn6+qapq5yeoe9FMo+RlGtsb/7v6MzOz6yusf/593+Ag5+hpHt9f/q8pq6ws4uMj29xc/f3+O/w8PP09Ly+wNXX2O3t7s/Q0i4sLf/7+P/28l1dX01NT+jo6eDh4jMyM6Kfn/3f0P/8+t7e3yMfIP///////yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRERGQjFEQzA1NjMxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRERGQjFEQjA1NjMxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgA/ACwAAAAAGAAaAAAG/0CfcEisEFjEpFJYwXgavSgOQSIsiZALNEorjVKDXgS1urI80QHphRUgejWXMvOObVRJyjAUw8GSHXA8QgJEGhh6PiA4DVZCDxE0ZSoOAUQUBxEKHiMXPSlDHQM2FqIKbEk8AAJsJT0gQjUAACMBJ4NKBACOkKAuNRBCKzU9LUkQxDV4PikRTSh7UQp5NTgeiSc9ArZDEMFXEBXfCz0bBydX6cI9KB4b6ukEPQEHoMcMBQUMM99EFj0OUMSwkWSGCQkSJsxY4glAi3lDdvjwRvHKmwcVcESANRGeEBc9aAhB0WPADY9D0AAQBmXAApQhQvYTEKFHDA39lrSI0OAkkToTNXsoaJFTCIEAPRr8USJgC5wAG0JgcJAihlCfS2y4isKV6wANGTwuGIGjaw+wKIdQENDBg4IR6YIAACH5BAUKAD8ALAMACAASAA4AAAZnwJ8QsxAahTzH7fjj/RQCJosmZB0dkRiASUD1DkXjI5ezQY6Q24XnY1IozLh8Tv+JjAmGrM7gSIQSEhwJO3I+Bnk6OiYFEwx3RjBCbXEze0ZFD3VMB0ibQgIRQhEXmxYDn0IvHThCQQAh+QQFZAA/ACwDAAgAEgAOAAAGZsCf8MQTGoUEAOH4W/16LSakJlQdQ72egvnoPQVHQLb3OK7GliOrFutAmI6ahvmDvOl4pimP3+NFeAkcBUwSEhMfRiBCBYlMHxOHQi4/RXwyBYQ/HkJpfEYYXkIknz8AEaVGBAGiQQA7";
|
||||
var smiley1 = "images/smileys/smiley1.gif";
|
||||
|
||||
var smiley2 = "data:image/gif;base64,R0lGODlhGQAaALMMAP//////zP/MzP/Mmf+ZZv9mZszMzJnMzJmZmWaZmWZmZjMzM////wAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyNkQ0RkQxMTA1QkMxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyNkQ0RkQxMDA1QkMxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgAMACwAAAAAGQAaAAAErhDICQxSKy+FDP2UgWlKqS0ISCGkF7Kb+42KrI42AKfqB4cZg6XTs1g2E4wHcUF9RJsO5iBxhkoUq8SQ0S1CCY+sc+F5RWaARqVxcS8ybiZd0Zg33+wc1E52VxwqBmEUOD2HhXuIiBlYHwIEBZIEA4JRCzYBA5OSBZU+KHKLAWyYABgKiyAsqXUxqltBEzBah3J0tDWHOyq0cwdCFiOmRcMnJ62LUMeysBMHTYogEQAh+QQFCgAMACwAAAAAAQABAAAEApBFACH5BAVkAAwALAcAEAAMAAQAAAQRcJRJ5hQA1JCzuF3YSWI5CBEAOw==";
|
||||
var smiley2 = "images/smileys/smiley2.gif";
|
||||
|
||||
|
||||
var smiley3 = "data:image/gif;base64,R0lGODlhFAAaALMJAP///8zMzJnMzJmZzJmZmWZmmWZmZjMzZjMzM////wAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1NTM4Q0EwNjA1QjMxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGQzBBMTE5MjA1QjIxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgAJACwAAAAAFAAaAAAEmBDISau9MxiECAYBYWzIYYidpXFjGpIBFSBGDIgrvRnUSBEsj2QmmCBsQw4yMBPOkKCdyHDgOI8VoGlEQMUGqV6YkgIKJ9IuYQCMFbA/jlwu3EBvViaTYGtnS3c8EicWQAgFfBqCUVkkciZQAl0ZeXp3UTVDPh9DOBJ+nIOLhKEgYSKlgwWfi6GoAAWtnAIdTamDcpecXboRACH5BAUKAAkALAEAAAATABoAAASYEMhJg0GI0ErMRYfRZZuFeWQwIsEUIEYLdCZ8GZNHEacmvQIJq4KRAQIvzct4vHUMB4xyuAN5RKPAgES5+CgZ3lfiJJgHvECBOuFh3lLAhTmTIpGEVnrDO9BxcmMSbgV5FoAWfB9vIUYCZi52d3SHMocbmCoxg2yYOYCBniVcHaIbBgWDoKYzgAWrpgIZSaxdb3SsZri1phEAIfkEBRQACQAsAQAAABMAGQAABJMQyBkCJabYOQk2BoKA5CYFIfgRQIAh7AmaBoGK+IaZQDjagQFI4uEACDDjrhfr/DwfQyVjvJFAiEMlyUFqKuAaskkcgTdiBK+FEx1KyPVABF2xyccsz0U0GHs/GygyPC8iIAU1FAU2ZTAeiXgoUmV4f5MWk3+XigAClJtdlChrm0ukoRyoQqWcNjOpXTiWqS6tABEAOw==";
|
||||
var smiley3 = "images/smileys/smiley3.gif";
|
||||
|
||||
var smiley4 = "data:image/gif;base64,R0lGODlhGAAaALMNAP/////MzP/Mmf+ZZv9mM/8zM8zMzJnMzJmZzJmZmWaZmWZmZjMzM////wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGNDE3QzIzNDA1NjYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGNDE3QzIzMzA1NjYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgANACwAAAAAGAAaAAAEqRDISY01NGuZFvvgkmxZAjJJcqTgSCogshnfssEoOXl29R06iskl+WB4mIkpB/AkaUkOQwYYRmk9Ra+yOHo+LtMxWmWILJUEhjZiCLvBidmwbcYpzvodz6DvN05uFAWEhYYFfABMEgGHhgIUZk2CEwOOBQNCOSZ6AoYEkHxJYBoBARucSqR3NH18RkGtZBJfcxoGOLOqJwu9tXA6dCfDRHEGHcO6e8cqJBEAIfkEBQoADQAsAAAAAAEAAQAABAKwRQAh+QQFCgANACwGAAUADgAKAAAENHCxZYAFibGEbUbeVl2WQZmSxmFTMl6Gm1BkbS12ru95QASWAmEgEAQEA0KhcFEun0+CJQIAOw==";
|
||||
var smiley4 = "images/smileys/smiley4.gif";
|
||||
|
||||
var smiley5 = "data:image/gif;base64,R0lGODlhGQAaAMQRAP/////MzP/Mmf+Zmf+ZZv9mZv9mM/8zM8zM/8zMzJnMzJmZzJmZmWaZmWZmmWZmZjMzM////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1MjQzQUI1MzA1REIxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1MjQzQUI1MjA1REIxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjJCMkQwNzI5MDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgARACwAAAAAGQAaAAAFyyAgjmLCMM/DKGTrAigkz/KTvGTyzMxdMjUcIMET7h6IVy3ha5lMkIfraNoxRjoIYwGL5rxYlSh68u2aQCfKdGI4xAAwAD4k43xAH4SkFQ5LfTpYTS8JDVdxUgqIfyMBAwQEASIMDQ0iKTCXQw0+BQegoAZDDoiZKCILDjcGoa6jfFJEWAADrrcDsXWMALe3sLuYeyIBBwUCLQIEwGeUYAGTfnVSI0HSI81YS9dA1CRAMrxTci3g4U0IUOQuWTTufdw77+LXVTTX+EIhACH5BAUKABEALAYACgAMAAgAAAUoYCRGwUAQwTgWR9saqnGo0QFHw0zXQ72PhlRBACgWBQRRoEgzMn+iEAAh+QQFFAARACwGAAoADAAIAAAFKGACjGQpksFAEMHInMUhywaQiMas18Cg/wPA72cIHAqCEkBAKLaUpRAAOw==";
|
||||
var smiley5 = "images/smileys/smiley5.gif";
|
||||
|
||||
var smiley6 = "data:image/gif;base64,R0lGODlhGgAVALMJAP//////zP/MzP/Mmf+Zmf+ZZv9mZv9mM/8zM////wAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQjUwOTkwMDA1QjgxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQjUwOThGRjA1QjgxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgAJACwAAAAAGgAVAAAEQxDISau9OOvNu/9gyAmFMQCEYQigcBjEe6QI6xWHNNSS+vkSG8BQ+OyEQd4nFZi4CCIBgUU6iYICQfPK7Xq/4LB4EwEAIfkEBQoACQAsBAADABMADwAABGgQyEAKERKIerMUBiIe2HCIyEFkwmlUKSEaxomsQGgEUoHiAR9JIBp4QgUP4DSQkTyE5/HmxGQoyhxiQNxmlcSnL/nNICchY9nJ+9Ss4BR8UjDMNQd7eVCAtwptZQBcAQIFaoJXAncZEQAh+QQFZAAJACwAAAAAGgAVAAAEoRDIOcgIcwpSiMjgcCDkQWQFqRYYSKhwAQQGrB7f9JIGt6Y8w4inWVGGvBwAiDgtSy3JDmFQSoAHiTETADpBQ4GgZJUMqNFMDSE4I3AggKAXl6zFpUFdXA8MJUNfdXE7MgA7BoODdxM1JoouRBojBmmDAiNwGZhUkHYkZRI0CIaLoJAvpSApmpBzqleklpADBUoFB3qedQMDG4K7cQECsyARADs=";
|
||||
var smiley6 = "images/smileys/smiley6.gif";
|
||||
|
||||
var smiley7 = "data:image/gif;base64,R0lGODlhIwAhAOZ/AP/69f/9+e4yKf/Zqf/jwfy2U/aSdPy0TP/r0v/u2bm7vYiKjP/16v/pzP29Z//x4vn5+v7Ge/R3WZmbnUlJS+nq6/Hx8lJSVbGztYSGiSUiI93e32prbfu8pmJjZnJzdjU0NSwpKv/48Hl7fv/esjw7PVtcXvz9/YGDhc3P0JSWmPy6XZaYm/7JhdjZ2/3i1cLDxezt7be5u8XGyH1/gf/Um/7t5UFBQvvDrf/mx9DS03R2eGVmaP/z5f3XxsvNz6Kkpnd5fP3Bb/yyR0dHSf/v3FVWWNbX2Y6QkiglJv///fuwQO7v8E1OUOPk5eDi4//47//8909QUufo6e0eJNvc3i8sLqSmqfb29//37e/w8GZoap6gotna27y9wPyyQ//05+rr7OXm5/P09IeJi9TV14yOkF1eYFdYWs/Q0j4+P/vItLS2uO89LpGTljEvMK6ws/q3n19gYqqsr+bn6Ovs7PFeQ/ijh+Lj5P/28aaoq/3Cc9HT1CMfIP///////yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZD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";
|
||||
var smiley7 = "images/smileys/smiley7.gif";
|
||||
|
||||
var smiley8 = "data:image/gif;base64,R0lGODlhGQAhAOZ/AOrq6//u2/jq5EtLTfr6+/7jyearlNqHc/39/f/27jQzNLGztSUiI3JzdcLExv7as+e6riwqK1laXJCSlYSGiMW9tv/69ctaTjo5O/zRqbi6vICBhP7To2lqbNna21JSVfX19fLy85+ho7O1uKyuseTl5v7LlGFjZcrLzYqMjnZ3eu/Wznp7ft7g4aurrNvc3qSmqdJzY//x4urEt/3FiaKkpu7cypeanNTV15OVmEFBQvLc08bIyiglJo6Qkv7Omba4umxtcHd4e9HT1KeprJqcnmZoaoyOkWVmaHx+gK6wskRERkdHSU1OUP/fvVxdX0JCRG9wcy8tLvf3+GRlZ19gYjg2OO/w8N7f4H6AgtfY2mBhY09QUtmThP/n0FdYWv7Yrj49P7y9wP/gvb/Bw/Xg1rKoofPo3czO0PuwXv/q04aIi/y/febn6Ojo6fv29PXUwfbOr+/KuVVVV+zn4tXX2NfAuDIwMfXFntDS09PU1ufVy9rb2yMfIP///////yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZD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";
|
||||
var smiley8 = "images/smileys/smiley8.gif";
|
||||
|
||||
var smiley9 = "data:image/gif;base64,R0lGODlhGQAcALMJAP///8zMzJnMzJmZzJmZmWaZmWZmZjMzZjMzM////wAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo5OEFGQ0QwRTA1QkExMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5OEFGQ0QwRDA1QkExMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgAJACwAAAAAGQAcAAAEuRDIKYUxKCNDqPeEtl1Y1n1UiZxUUAYooLFoYH6YMQSwFxSXEKInCZFyxMGKx8tQMkRAgBUtriS2asyDKRooBK3UkLySJ0bUa7KRPTHaA4fYRaAEH5qkvu3v7UN+W10cHy5rKAgHAF1cBGRpPm0CbU8AHWRnKYEyVxOQLoxRNnZWGwRhqC5TF5t4n04XPKJfpYyVmx22IVMdLrhcnC0HjzeDBR8imluhm8aCwqTAfjY6IXqCaM/Z3CgRACH5BAUKAAkALAUADAAMAA8AAARCEEgQjEEozGmICQRibAACEMD3bR9RpRXhyhVojVagqWVXTiFQKEOijDCFIvEyYrVOREkAg5GKBkPqZnigNovgMCACACH5BAUKAAkALAUADAAMAA4AAAQ/EMhJKwjGIBSsIUZAIEaFAAQQhlRIYCpGvDMmZmcWdCuwpSfJSDTiWGCaggUxQ5Vam6BREogGq4ZBcfMU/igRADs=";
|
||||
var smiley9 = "images/smileys/smiley9.gif";
|
||||
|
||||
|
||||
var smiley10 = "data:image/gif;base64,R0lGODlhFwAbAKIAAP///8zMzJnMzJmZzJmZmWZmmWZmZjMzMyH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNUM2RjcwRDA1NjcxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNUM2RjcwQzA1NjcxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQECgAAACwAAAAAFwAbAAADhQi63P4wyklVCPWRc0hmQScc2AcEhtKZZwoYnoliMwsrhFFmW5kPkwBhuCFZhpGQwcA5FHYvKAOJY0JzEOHlYgUZHcomBzr4NmBb4WrRexyAJ3WsCtksl5w5APsIEdIHLgoDgg0hO0U7NxAFgRwwOlyFD0wEA2p3enWBS0MCFxlaLKOkDAkAIfkEBAoAAAAsBAABABEAGAAAA3gIuhDBEJpzSIyk5neXKUrVeRZgGKNSlMPBdQSqnGkgNvSYlUD8BqfP5KYgWGzCIU8BDBgXTsprZnD+pBLXYUjBMiYno3iyNFHKGdA3OFZKqhQ2WFKwLW0HieXjMJ4OAgs+DV1bBECHMS6Chk5gjQxAW2EODh2VKQkAIfkEBGQAAAAsAwAAABMAGwAAA4wIuhr8EIRDSYzmkOwu0xLoNUdnGONSKsSRKuJkpefSdl47Aze9sgcUg0AkZkQNIYDCZBJwLFRAGWgFIbLqY/L7uAyCgHhDgcJKzfQAQjmJ31ylKrNbZOShk6a6OdZhBVxMJ3dsFkFQXGxrBwUMU2VDLjxBehVIOjZMgSFGFY9BAgJkg39AbU9mF2IvCQA7";
|
||||
var smiley10 = "images/smileys/smiley10.gif";
|
||||
|
||||
|
||||
var smiley11 = "data:image/gif;base64,R0lGODlhGQAaAMQAAM/R0u4oKP///yQgIYeJjHFyda2vsTs6POjo6fP09PikiPJmSvr6+/7q4P3czpOWmP/49Z+hpMPFx//y7GFiZfvAqf39/fb29+Hi47i6vNna3P/8+VhZW+/v8AAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0MjAyMUUzMDA1RkMxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozREVBMjcwRTA1RTYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjlCMkQwNzI5MDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQECgAAACwAAAAAGQAaAAAF/6AgjgJAUMcwHBwhWWQ8SpS6cgWqHgYsCwyCrSC5CHyaR4qCkV0KKg7g+ENAD5qYcPBg/GKRFWIEUEm+v8eAMoKe0TIL1CBAcEeYtwwxFWEGHAwGBwl+KREyZQMEI0ISBYgiYSodMWoqYyWLUiIWBjZ0JJcDTUAsB5UiHSkFqSMaKYwjHClGIwyZe1kkNQO7cGg1PMBoFgcHFBw+xDEaa0IZJBbLxWoPZQdjyxAbJBswPgkpWTUcrhAKC+oLAQrdI2oFIormIg3qAfkLFRBkKxo+JnGQ4EUAhAYN+pEAkCJUIxscMjCgJiLBpQgUBUzaQcCAhI8RCqQ4EO2Lhl42UhWqKJALzSOVO0oxE9DBAAFaKjD+CAEAIfkEBAoAAAAsAgAQABEABwAABUVgJozWZo1oKhzMuC1LBaVONW3Dc0JL4MO9wKIhGAwKCIGlEvwpNqOI8RA5jSaNmephHHAyLWUqobMYuoMDwSBpRwqHQQgAIfkEBGQAAAAsAgAQABEABwAABUlgJgjNomxjOm6VciBkECwVpDrL0gxcJ+CyWU62cAgGPIwAUlkEZwqIRRBBHiKM1KRhUwkISF4mK5imEo+yITw4EAySeKRwGIQAADs=";
|
||||
var smiley11 = "images/smileys/smiley11.gif";
|
||||
|
||||
|
||||
var smiley12 = "data:image/gif;base64,R0lGODlhGQAaAMQRAP//////zP/MzP/Mmf+Zmf+ZZv9mZv8zM8z//8zMzMyZmZnMzJmZzJmZmWZmmWZmZjMzM////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3MDUyNTUzNTA1ODgxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3MDUyNTUzNDA1ODgxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgARACwAAAAAGQAaAAAFwCAgjmLSPOjjNGTrJg8kQ+j8JG4byw0+wrycaMcSAh25na9lQgGLP9mStID0ErjYVCtcuBC0qM/UE44aEN8JgIiVzaMwYAV4QHOJYB0yxE3xVmdpAHx4LoUlg4Mtej8keTiLPzd3LgqDdnA5BABoOGiaLgeEhXkPoSMGBqZxgZoBBgcCXCIMjSIDASICBQcHBGinJDvCAL2+yAcDeYjDM0UEqgYFA51SQjs8WFgMaDR/Ld4z47dw4uSoTCdK6e0kIQAh+QQFCgARACwIAAoADwAJAAAFHGAkjuQYlGiqRqegrGIgCA2MBqctCjrL27McLAQAIfkEBQoAEQAsBwAKABAACQAABR1gJI6kGAhCqYqooKwlOsB0rZ6pHcn6Psy6QE8UAgAh+QQFZAARACwIAAoADgAIAAAFE2AkjmQklOhIEGnJtnAsk+v8yiEAOw==";
|
||||
var smiley12 = "images/smileys/smiley12.gif";
|
||||
|
||||
var smiley13 = "data:image/gif;base64,R0lGODlhGAAYAMQRAP//////zP/MzP/Mmf+Zmf+ZZv9mZv9mM/8zM8zMzJmZzJmZmWaZmWZmmWZmZjMzZjMzM////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2QjQ5NEEwODA1QjExMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2QjQ5NEEwNzA1QjExMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgARACwAAAAAGAAYAAAFoyAgjokDnSjkLGPrmueazAusuCTKJDiQnCzc6cHrjUzBo8qIQ+YczN5p1IBEfYtF8ReEFBUoRzFbgwRNPiu2yAwuvAnG1cjNzo0q+124SroCAgQEA1IrD0YCBQcIB4QtPw0/bC0DBQYHBY4jbyxLOAIGlgUCL14ATp8Cqi4/UGlme6emIm+wc2+uSiqTOLg9MLu9MW0pKg7AtkwlxWG8UWUpRiEAIfkEBQoAEQAsCQALAAcACwAABSRgNBDEIETCgSDHQQgrEiFFGt0GERhtO6CiUuBGLBqPSOKjGAIAIfkEBWQAEQAsCAAHAAkADAAABS1gJI6OMyZjqqrBILyjgMzzIR6ISA9GniKFnmoWoOkQhAiBZhQVmIKUYDAYhQAAOw==";
|
||||
var smiley13 = "images/smileys/smiley13.gif";
|
||||
|
||||
var smiley14 = "data:image/gif;base64,R0lGODlhGQAaAMQTAP/////MzP/Mmf+Zmf+ZZv9mZv8zM8zM/8zMzJnMzJmZmWbM/2aZmWZmmWZmZjOZzDNmZjMzZjMzM////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3QjY3RTVCNTA1QjYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3QjY3RTVCNDA1QjYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFFAATACwAAAAAGQAaAAAF6iAgjkDiOFIqOQrpuoq6nmjavmQt3SRSIziAiodD2F4oBzA4MkqWopiDCfCpaqSUj/VyNhiNyLH6FJnKIqPjwWZjAYppWsGQA1DtPGR3B6ppSysLAAt5DCtCUUESDQmEhimJVIxsBwAHbIcSkkx4DyNse5toIwE9Kw+WmA0rm1wkBQWnjGBiCRIRd5skAgYDPTpKaiWIJAQGBQIBAQOyAIcnaGMjAgUG1wRVES1OIzF8LssjSlUoRDV2OK07cS46RCQxN+3uMgwI+PhxLEm7MDIAhwRi8i1gHAVxijFBkDDFFIQIX1EpwlBhCAAh+QQFFAATACwMAAMACwAXAAAFdeA0IY4kiehoNkwTTYrqPDTtjGWtQ6WzAAvUgzGRNBLAFHHSoB0Ah1TuAaiKILIUU+IAIFatiIRUJZm4CICoymZw1esAIqJQx6RpRENbLEkUdygKf1UKNygIMD0nKAA3iQCMKCeGXHwwhoEiCIlvWmxsn6ATIQAh+QQFFAATACwKAAMADQAWAAAFieAkTkCJjCjiiJKDSNMZww3TRJICA+/0oI5cLvgoFkUQx6q1ACyOE0ZuImkknL6iFEBtFA+Ag1YCUEqKJUAxyX05HmAxFcGdVW2RWF2kkvhdJShALSQyKDk8V4ITgAgNLjCHQSI6EgkoOgolCiJ7MQ6cEjgkgqB0AGSelApBDoGLCqyaizE6KyIhADs=";
|
||||
var smiley14 = "images/smileys/smiley14.gif";
|
||||
|
||||
var smiley15 = "data:image/gif;base64,R0lGODlhHQAaAMQSAP//////zP/MzP/Mmf+Zmf+ZZv9mZv9mM/8zM8zM/8zMzJnMzJmZzJmZmWZmmWZmZjMzZjMzM////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1REJDRURCMDA1ODYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1REJDRURBRjA1ODYxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgASACwAAAAAHQAaAAAF6SAgjiSgNE+kRk+jlDCspOtjr1ETx039kifV47cD0IZFo4oI6+WOTJJzp1i6FKcHY9d7xFJRma01iyxguSQQFalCSEfdKFw69V4ob7ttgqTVVToQVQAuDTpsciUpiiwzAA6IjyKHMisJIikOaRFGAJ0Mh2FVWCM0RicnRiieMjApZDlyd4RqIksRCQtEqny2VV6sTQ8FtoV/La8HCAcCMAIGI0sipCURAsvMBQQEBcsDlCxwXqbkA9kI6QbOJtNzLGx/IgED9QHv8vg4SFwqiv04GuzCEs8XIBo4EpIzRg1hQjoMQyH8RyIEACH5BAUKABIALAAABwAOAA8AAAVToCRKymiaivM80dOcEiA1EeBGJfrYwKK4sEepoWgYTy8Fg9hYNADQGfExIzUYxReg9jKpJEKAMTqiKiKiUm6kGKJO6/LOBETh2JJEcOaA6cBUJyEAIfkEBQoAEgAsAAAHAA4ADwAABVKgJCbiI54oYEZN9CioqLyP2phoIzWKAywKF4rVUAEkM5isRlPNUqabiFdTHHc8CePU6OpKsVbxFTspti1Z5HpaSE+s8hb1wCF1bLXJXj49vjEhACH5BAUKABIALAAABwAOAA8AAAVToCQCYiOeqOJIT/Q0JMo2EfBGipzbwKK8ptPjoWg0csaYxGFUMI6NRbBkeomKjGKwZpo6iI/T9PoAKGqyk3k2IuoeB9QwPZac1bmEzBZZptMufyEAOw==";
|
||||
var smiley15 = "images/smileys/smiley15.gif";
|
||||
|
||||
|
||||
var smiley16 = "data:image/gif;base64,R0lGODlhHgAaAOZ/AJyeoTQzNG1ucMjKzJaYm83P0Kqsr3l7fcDCxJSWmLe5u3x+gFJSVWFjZfLy84mLjZ6ho3BxdLq8vtzd3qOlqGlqbNXX2D08PoSGiIaIi5qcnpeanOHi411eYCUhIsXHydrc3by9wCkmJ3V2eaKkpmpsbnp8f66wskRERqyusaCipeTl5oCBhH6Agm5wctLT1VVWWKWoqpGTlYyOkTk4Ob7AwmZoak1OUMvNz4KEhrS2uFNTVUZGSEtLTXJ0do2PkkxMTsPFx1pbXXd5fEJCRC0rLO3t7ickJf39/ZOVmDs6PFhZW+rr7Onp6mBhY/z8/Dg2ODAtL+jo6ezt7SsoKenq6y4sLU9QUu/w8N/g4fr7+4uNkPb29/P09O7v8FBRU97f4EBAQSwpKlxcX6+xtMnLzPDx8fn5+uvs7NPU1ubn6NjZ2+Pk5fHx8mZnaaiqrUhISpudoFdYWj4+P7CytPf3+O7u7zw7PTIwMfj4+fT19dTW16eprCMfIP///////yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0NDAwNDU5RDA1REUxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0NDAwNDU5QzA1REUxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjJCMkQwNzI5MDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgB/ACwAAAAAHgAaAAAH/4B+goNlGSM/ZGuDflIfVU59FwWLlIIvDS6TlS8iAR4BCSViJhKVgiQ8CH5cQQApYIMVFXxLQnwAfQx9EJUkDFJGDzsQK4tpUSN8Pld8fAx8cEuUBSgrOCgbeZRDRUdjfC0ofCpufDA7lGMIexdBfi85LTpdfh4tCTR8P0p8GzbOAhbhcHHmiwQkM658WCTCBJ8wBAAU4bPFCR8USRZlKHPigJ8NDdpQYlCCjxwXfETEWNCATwBVg0b4KcGBCY8pfpjIIGHETxxxLkRcgcLDRYsYHnoOSoJE5gkKfuwo6dNHhIwXfQCoAFLGDJ4h/eagsXGjwwkEUlL4nELihggvZf8E9LnigcXDKn4adNCHAo8TACQutOGgxg8IGDTGiDAgaEAPDz344LHgR0DLDFQwNMO8aEKfLH66JCmBAMmZHx4EKDnh5wAMPgTi8NHQ4AiARU36MBbERMCNEIa/eDDhR0MRCs0WiIjAYZqIPjsM0POjg8YAP0hi/PDTRMw/1LspXViAoEWAKDkoM5FSCYKHBChKmPJzRIEgLQgO4IGBw9STG0pEgZMpC8yxwQSDcOEDa6YA4EEZ8wmyAFVQNJDDFjcoVYkBfUQoSBZ9IDBFCBHQwEKEqnnIXR8aOKCiH2D0scCLPvRRhA1JhMDGfHJB+CIICUTwWB9WLKGBBU/44UAjBn3A8GIlRpwgwHNE8lBEHx4s9KQpWJBxAArP3WDflmTOFwgAIfkEBQoAfwAsAAAAAB4AGQAAB/+AfoKDhIWGh4gcCQcydGuIkIUOD2M1SIVSH1VOfRcFkYIrDABaaipbbyB+LyIBHgEJJWImEpBtDApmOQ01WoMVFXxLQnwAfQx9EIg5GqIqSHkvHw5pUSN8Pld8fAx8cEuHHEJcSzpPGjAQakNFR2N8LSh8Km58MDuHBCExGUgHCytkkPDQIgENPj+gwLgDhQIDAYeGPGngRYEAI0r6aNxBIQwBAGHKmIkyBEWSQwmqZPATgcANEV7KVOgThoELPjSq+OnQIQCCQyHKfJpDY4wIA4IG8BAhwkQRC35KNPBg5BCWNE8m9Mnip0uSEgiQnJHhDsoJPweuzEFj40aHs4XRmvRBKohJiR4h/Ez44sGEHw1UUOBxAoDEBUMFRPTZYaCLoBMBBvhBEuOHnyZUjmDYloGKoQsLELQIECUHVCZSDEHwQEBDgyMADB1RIEgLggN4vnw49OQGChEROBxaMGfDhEFcBKRAtJouogUaoTTIseVG1UMG+oDK0gfBlBARaLCA1IAGKLkaHIDyA6bPgvU++hSxkSQEG0Ql+pRZ7wdEggg9eNCHFUtoYMETfjiQQR8w8FeIEScIoNiAPBTRhwe7OWgIFmQc8FsfN9Cm4YiGBAIAIfkEBQoAfwAsAQABABwAGQAAB/+AfoJ+em8tSXRrg35SH1VOfRcFi5R+CkIpdZUvIgEeAQklYiYSlX4aJVgWGQ8GIIMVFXxLQnwAfQx9EJQKJQ4YPmCUaVEjfD5XfHwMfHBLi11yaAIAfggZJ15+Q0VHY3wtKHwqbnwwO4tvBiRbXC4YTIMeLQk0fD9KfBs2ywKLJnqccMmwa5EIE3zCEABQhM8WJ3xQJFmUoAAJLCUqMSjBR44LPiJiLGjAJwCCRSEMTMFx0g8TGSSMxBHngooLHndomIjhwcgiI5NAaPFjR0mfPiJy9AGgYsGNMmbwDNkwB42NGx1OLKpD4oYIL2UEHDWWsIqfBh1+oMDjBACJC4v/YNAYI8KAoAFEjjzgg8eCHwENMlDBoEzwoAl9svjpkqQEAiRnHogQoETrARgE4vDR0OBINUFN+tgVxETAjRB+JnzxYOJUEQp8FoiIwGFRARF9dhjoIkgHlAF+kMT44aeJGBs/PIxedGEBghYBouTwy0RKJQgewmSsdESBIC0IDuCBgcPUkx5HpphaMGfDhEFcfGg1BcCKKUELjkJpkGPLDZ+mGNDHfX5k0QcCU4QQAQ0sEEgZgaFp4ACBg4DRxwIU+tBHETYkEQIb94lVBoV+gJBABD140IcVS2hgwRN+OJBBHzCQSIkRJwiA24o8FNGHBx/YaAoWZByAAm43eFdJASAAOw==";
|
||||
var smiley16 = "images/smileys/smiley16.gif";
|
||||
|
||||
var smiley17 = "data:image/gif;base64,R0lGODlhGQAhAOZ/ANDS0/n5+vBHM0ZbZgCj2gCRuLm7vfz8/Ds+QUpKTP3i1ePk5fHx8sHDxTQ0NomLjfX29j1GTEZTXISGiLGztkdsfDiBnCUiJO84LACcy5qcn6WpqwCr7Ds8Pvqzmnp8f7y9wGttcEN2i8vNzy0rLMbIypaZmyyHpv7s4/ijh0JCRZGTlnJzdkxNUACh1vzJtUVxhNna28jKzIKEhl1eYJSWmI+RlJ6gogCo5X1+gbe5u2FjZTx+l1VXWQCm4EhkcllaXACe0K2vsV5fYkZGSNvc3jSDoEdgbTY6PiclJvNtUACYxACXwu0cJOzt7d7f4P/8+t/g4e/w8NbX2c7P0c/Q0m5wcuvs7O7v8EJOVurr7FNTVYaIi//7+N3e37S2uCkmKPeegb7Awqqsr42Pkv/9/U+JokR5j66ws3V3efP09EZvgZyeoTY3Ofecf6GjpaSmqfzNun+Bg/WIai0uMOjo6TAxM2VmaGdoawWOslVYW/3ZyQCu7yMfIP///////yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCQjM2NUVEMjA1RDkxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCQjM2NUVEMTA1RDkxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgB/ACwAAAAAGQAhAAAH/4B+goN+ASMmDw2Ei4yEOh19YG19K35qB42NMUkDBTgcMH1JfX0IIRsMmYJvfTh8OEEEFTxGFjBZfXY2qY1CfQNZF0h8xMV8QRUXKjEyi1gapEgwS8bVGWdmEhuCEGxtF0cFHMQ+LgTj1cQFCH4ALX0/QXw+Jz9IEUcVMCeu1QV9JUhEoMbkRwQYBXxUc3XkiJECRhD0QCDBRxARPDK4yCNCggOKFSxk4GAhAqk+Q56AQcKEQIEjozqEmLCCC4sWF/p0WFPAwoUZghzYEWGSiI0pjA6UoJADEhg6egTl6tPDwIEAJdAAWCQmQY0DI4Zc+CA1iQZBMVrsuIF0kZYhNf8sORgi6AaNQWmoqPIjA4igCX3q+DFxVtCXHFoYTTEQgggIQQb66PAj57GgIn1IbBlByAYpLoO89DHhx4qYzkAeBCCklAKEQVj6PCgNZ6+qBbL95GBhO1ODPmdvkLjCSIGHMCledGFEps/jKn2ADtqjpIl16wJesG6RRIqgBBcU+UGBQUAKBX7KKHCDIc4gEH14CxrTx4FeKB5QFJ/DDedWQQEMkRkFe0HhxwE59DHBIguoQIoVC6gCwQd97PDaIk8QQQoYH1SBySBObKAhHt414kQIJ5VCww53gBdJDavtBUIPKab4QRS9CQLWBAmkuMWHORJyhQwUCIFjkEgmmWMBIAAh+QQFCgB/ACwGAA8ADAAJAAAHRIA5Tn6EhU8AXC0OXCNRhX5FdSUGFAsQB48HBwGYj56eCh5hKS9dj3tKTaqqAi+EKBgCKQp+ZQpuGHF+UB4onwpzn8KBACH5BAVkAH8ALAYADwAMAAkAAAdFgDlafoSFUwYhRH0kWyOFfjZ9fVw2QA8BjwclFBCPnp+gngoeYSkvXY97Sk2srAIvhCgYAikKfmUKbhhxflAeKJ8Kc36BADs=";
|
||||
var smiley17 = "images/smileys/smiley17.gif";
|
||||
|
||||
|
||||
var smiley18 = "data:image/gif;base64,R0lGODlhGQAZALMPAP//////zP/MzP/Mmf+Zmf+ZZv9mZv9mM/8zM8zMzJmZzJmZmWZmmWZmZjMzM////yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0M0ExQkM1NjA1NkQxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0M0ExQkM1NTA1NkQxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgAPACwAAAAAGQAZAAAEtxDICdJqGK9Ee0+NIzrY2HAexYwbZYlLKoUOI1dhky4iegM8m6vHc8Rci1ZIQQn5QLoZKSkRUYyeVtInUWBxrhwHJDpNSBJqmuRgSsgXFG/mO4WOOMe4qweYkVwJXBVYfz8pCYV4EgEBh4QxGB0DBwUCEwIFAxQ8HJ0UAgiio6KXEyFvaB0EBAYGlh+qfl+PUk8wtYRRE0WGMol9HTS0WT0yRWWCggrIg7Ej0Cy5F9FWuRMWJcQdEQAh+QQFCgAPACwFAAgADQAOAAAEMfCpR6utrqVbF01ABSSeCIQmp1rCKgRPcCAq0j7EOlwz4hcqgcFnuKkCsJVyqSp9KhEAIfkEBWQADwAsBQAIAA0ADgAABDHwpUerrSuBCjpt3WaFV2mewjMU53M8BNIObW0b8oPQZYH8iIApAGSdAgSeqaGoNCkRADs=";
|
||||
var smiley18 = "images/smileys/smiley18.gif";
|
||||
|
||||
var smiley19 = "data:image/gif;base64,R0lGODlhGQAZALMOAP/////MzP/Mmf+Zmf+ZZv9mM/8zM8zMzJnMzJmZmWZmmWZmZjMzZjMzM////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDJFODNBMDA1ODkxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDJFODM5RjA1ODkxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNFODNDRUIyNDIwNjgxMTgwODNDQUJGRjcyMERFNzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCgAOACwAAAAAGQAZAAAEtRDIKZNaba10qP9JI45k8nlH2U0I1qxf2jBwLNaTyB2cl/wyXCiByGhMld+CEWp4GibkicKDThKLqRaAmSxqm9MBFlo5rzeULmc6ZL2iN1rkzbopTWklDgckGD44EhowXSFbW0sAKXoUAQQEAgEfGRJ0HwEFBgYFAmpIGI0AA5ubBB4YK0EeApqcnhMpclxpHgG3qC9UI6IfoTZxghJulWIkGzBVVokkzRnCMS4kCtBaPC69ExEAIfkEBQoADgAsAAAAAAEAAQAABALQRQAh+QQFZAAOACwIAA0ACQAGAAAEGBBIQQqRkphtihwcNwAhRwTlNg6DQBFXBAA7";
|
||||
var smiley19 = "images/smileys/smiley19.gif";
|
||||
|
||||
var smiley20 = "data:image/gif;base64,R0lGODlhFwAZALMNAP/////MzP/Mmf+Zmf+ZZv9mZv9mM/8zM8zM/8zMzJmZmWZmZjMzM////wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowNTgwMTE3NDA3MjA2ODExODA4M0JGM0E0OEZDMzA1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpENTFGRUVFMzA1ODAxMUUyOURBQUJGODExREIyNkYyMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpENTFGRUVFMjA1ODAxMUUyOURBQUJGODExREIyNkYyMSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQzOTBDOUU4ODIwNjgxMTgwODM4QkU1NzkyNUFFNzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDU4MDExNzQwNzIwNjgxMTgwODNCRjNBNDhGQzMwNTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFCAANACwAAAAAFwAZAAAEvhDIKVNSytK9L/vgl3GUAi6ZpSwiCbDMkpAJu3Cw4gKzeU8mhmWBKsV0vslHNdS9UDMJa5YQdmQ1IssZA6yMMgRnZKpFn+cdgmGi/HZuIhxum+9gm0CAFCgUJjBnAQcGAwN7AAEDAgQHgC0SgwICAIsCAwCTBkpEVhIEAZR7epWKEiYYXRKLlZOLmIcSSwAfbwSZEpQCoaeqVaoABJi4rDwfRpCKAwSUFbPIkBQ1zx0htTC1aWPWJ9o7K9beABEAIfkEBQgADQAsBQAMAA0ACQAABDUQhACqlaWEY8ag0iAQxyYIgCgMwGkARIBSUxqwYnqKOEi0FZRAdiGwgLlLaEBAWRgKpTIRAQAh+QQFCAANACwAAAAAAQABAAAEArBFADs=";
|
||||
var smiley20 = "images/smileys/smiley20.gif";
|
||||
|
|
81
toolbar.js
|
@ -1,6 +1,4 @@
|
|||
var Toolbar = (function (my) {
|
||||
var INITIAL_TOOLBAR_TIMEOUT = 20000;
|
||||
var TOOLBAR_TIMEOUT = INITIAL_TOOLBAR_TIMEOUT;
|
||||
|
||||
/**
|
||||
* Opens the lock room dialog.
|
||||
|
@ -199,61 +197,6 @@ var Toolbar = (function (my) {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the main toolbar.
|
||||
*/
|
||||
my.showToolbar = function() {
|
||||
if (!$('#header').is(':visible')) {
|
||||
$('#header').show("slide", { direction: "up", duration: 300});
|
||||
$('#subject').animate({top: "+=40"}, 300);
|
||||
|
||||
if (toolbarTimeout) {
|
||||
clearTimeout(toolbarTimeout);
|
||||
toolbarTimeout = null;
|
||||
}
|
||||
toolbarTimeout = setTimeout(hideToolbar, TOOLBAR_TIMEOUT);
|
||||
TOOLBAR_TIMEOUT = 4000;
|
||||
}
|
||||
|
||||
if (focus != null)
|
||||
{
|
||||
// TODO: Enable settings functionality. Need to uncomment the settings button in index.html.
|
||||
// $('#settingsButton').css({visibility:"visible"});
|
||||
}
|
||||
|
||||
// Show/hide desktop sharing button
|
||||
showDesktopSharingButton();
|
||||
};
|
||||
|
||||
/**
|
||||
* Docks/undocks the toolbar.
|
||||
*
|
||||
* @param isDock indicates what operation to perform
|
||||
*/
|
||||
my.dockToolbar = function(isDock) {
|
||||
if (isDock) {
|
||||
// First make sure the toolbar is shown.
|
||||
if (!$('#header').is(':visible')) {
|
||||
Toolbar.showToolbar();
|
||||
}
|
||||
|
||||
// Then clear the time out, to dock the toolbar.
|
||||
if (toolbarTimeout) {
|
||||
clearTimeout(toolbarTimeout);
|
||||
toolbarTimeout = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!$('#header').is(':visible')) {
|
||||
Toolbar.showToolbar();
|
||||
}
|
||||
else {
|
||||
toolbarTimeout = setTimeout(hideToolbar, TOOLBAR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the lock button state.
|
||||
*/
|
||||
|
@ -261,30 +204,6 @@ var Toolbar = (function (my) {
|
|||
buttonClick("#lockIcon", "icon-security icon-security-locked");
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the toolbar.
|
||||
*/
|
||||
var hideToolbar = function () {
|
||||
var isToolbarHover = false;
|
||||
$('#header').find('*').each(function () {
|
||||
var id = $(this).attr('id');
|
||||
if ($("#" + id + ":hover").length > 0) {
|
||||
isToolbarHover = true;
|
||||
}
|
||||
});
|
||||
|
||||
clearTimeout(toolbarTimeout);
|
||||
toolbarTimeout = null;
|
||||
|
||||
if (!isToolbarHover) {
|
||||
$('#header').hide("slide", { direction: "up", duration: 300});
|
||||
$('#subject').animate({top: "-=40"}, 300);
|
||||
}
|
||||
else {
|
||||
toolbarTimeout = setTimeout(hideToolbar, TOOLBAR_TIMEOUT);
|
||||
}
|
||||
};
|
||||
|
||||
// Shows or hides the 'recording' button.
|
||||
my.showRecordingButton = function (show) {
|
||||
if (!config.enableRecording) {
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
var ToolbarToggler = (function(my) {
|
||||
var INITIAL_TOOLBAR_TIMEOUT = 20000;
|
||||
var TOOLBAR_TIMEOUT = INITIAL_TOOLBAR_TIMEOUT;
|
||||
var toolbarTimeout;
|
||||
|
||||
/**
|
||||
* Shows the main toolbar.
|
||||
*/
|
||||
my.showToolbar = function() {
|
||||
var header = $("#header"),
|
||||
bottomToolbar = $("#bottomToolbar");
|
||||
if (!header.is(':visible') || !bottomToolbar.is(":visible")) {
|
||||
header.show("slide", { direction: "up", duration: 300});
|
||||
$('#subject').animate({top: "+=40"}, 300);
|
||||
if(!bottomToolbar.is(":visible")) {
|
||||
bottomToolbar.show("slide", {direction: "right",cduration: 300});
|
||||
}
|
||||
|
||||
if (toolbarTimeout) {
|
||||
clearTimeout(toolbarTimeout);
|
||||
toolbarTimeout = null;
|
||||
}
|
||||
toolbarTimeout = setTimeout(hideToolbar, TOOLBAR_TIMEOUT);
|
||||
TOOLBAR_TIMEOUT = 4000;
|
||||
}
|
||||
|
||||
if (focus != null)
|
||||
{
|
||||
// TODO: Enable settings functionality. Need to uncomment the settings button in index.html.
|
||||
// $('#settingsButton').css({visibility:"visible"});
|
||||
}
|
||||
|
||||
// Show/hide desktop sharing button
|
||||
showDesktopSharingButton();
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the toolbar.
|
||||
*/
|
||||
var hideToolbar = function () {
|
||||
var header = $("#header"),
|
||||
bottomToolbar = $("#bottomToolbar");
|
||||
var isToolbarHover = false;
|
||||
header.find('*').each(function () {
|
||||
var id = $(this).attr('id');
|
||||
if ($("#" + id + ":hover").length > 0) {
|
||||
isToolbarHover = true;
|
||||
}
|
||||
});
|
||||
if($("#bottomToolbar:hover").length > 0) {
|
||||
isToolbarHover = true;
|
||||
}
|
||||
|
||||
clearTimeout(toolbarTimeout);
|
||||
toolbarTimeout = null;
|
||||
|
||||
if (!isToolbarHover) {
|
||||
header.hide("slide", { direction: "up", duration: 300});
|
||||
$('#subject').animate({top: "-=40"}, 300);
|
||||
if(!$("#remoteVideos").is(":visible")) {
|
||||
bottomToolbar.hide("slide", {direction: "right", cduration: 300});
|
||||
}
|
||||
}
|
||||
else {
|
||||
toolbarTimeout = setTimeout(hideToolbar, TOOLBAR_TIMEOUT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Docks/undocks the toolbar.
|
||||
*
|
||||
* @param isDock indicates what operation to perform
|
||||
*/
|
||||
my.dockToolbar = function(isDock) {
|
||||
if (isDock) {
|
||||
// First make sure the toolbar is shown.
|
||||
if (!$('#header').is(':visible')) {
|
||||
ToolbarToggler.showToolbar();
|
||||
}
|
||||
|
||||
// Then clear the time out, to dock the toolbar.
|
||||
if (toolbarTimeout) {
|
||||
clearTimeout(toolbarTimeout);
|
||||
toolbarTimeout = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!$('#header').is(':visible')) {
|
||||
ToolbarToggler.showToolbar();
|
||||
}
|
||||
else {
|
||||
toolbarTimeout = setTimeout(hideToolbar, TOOLBAR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return my;
|
||||
}(ToolbarToggler || {}));
|
|
@ -381,7 +381,9 @@ var VideoLayout = (function (my) {
|
|||
// If the container is currently visible we attach the stream.
|
||||
if (!isVideo
|
||||
|| (container.offsetParent !== null && isVideo)) {
|
||||
RTC.attachMediaStream(sel, stream);
|
||||
var simulcast = new Simulcast();
|
||||
var videoStream = simulcast.getReceivingVideoStream(stream);
|
||||
RTC.attachMediaStream(sel, videoStream);
|
||||
|
||||
if (isVideo)
|
||||
waitForRemoteVideo(sel, thessrc, stream);
|
||||
|
@ -1248,7 +1250,9 @@ var VideoLayout = (function (my) {
|
|||
&& mediaStream.type === mediaStream.VIDEO_TYPE) {
|
||||
var sel = $('#participant_' + resourceJid + '>video');
|
||||
|
||||
RTC.attachMediaStream(sel, mediaStream.stream);
|
||||
var simulcast = new Simulcast();
|
||||
var videoStream = simulcast.getReceivingVideoStream(mediaStream.stream);
|
||||
RTC.attachMediaStream(sel, videoStream);
|
||||
waitForRemoteVideo(
|
||||
sel,
|
||||
mediaStream.ssrc,
|
||||
|
@ -1288,5 +1292,84 @@ var VideoLayout = (function (my) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* On simulcast layers changed event.
|
||||
*/
|
||||
$(document).bind('simulcastlayerschanged', function (event, endpointSimulcastLayers) {
|
||||
var simulcast = new Simulcast();
|
||||
endpointSimulcastLayers.forEach(function (esl) {
|
||||
|
||||
var primarySSRC = esl.simulcastLayer.primarySSRC;
|
||||
simulcast.setReceivingVideoStream(primarySSRC);
|
||||
var msid = simulcast.getRemoteVideoStreamIdBySSRC(primarySSRC);
|
||||
|
||||
// Get session and stream from msid.
|
||||
var session, electedStream;
|
||||
var i, j, k;
|
||||
if (connection.jingle) {
|
||||
var keys = Object.keys(connection.jingle.sessions);
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
var sid = keys[i];
|
||||
|
||||
if (electedStream) {
|
||||
// stream found, stop.
|
||||
break;
|
||||
}
|
||||
|
||||
session = connection.jingle.sessions[sid];
|
||||
if (session.remoteStreams) {
|
||||
for (j = 0; j < session.remoteStreams.length; j++) {
|
||||
var remoteStream = session.remoteStreams[j];
|
||||
|
||||
if (electedStream) {
|
||||
// stream found, stop.
|
||||
break;
|
||||
}
|
||||
var tracks = remoteStream.getVideoTracks();
|
||||
if (tracks) {
|
||||
for (k = 0; k < tracks.length; k++) {
|
||||
var track = tracks[k];
|
||||
|
||||
if (msid === [remoteStream.id, track.id].join(' ')) {
|
||||
electedStream = new webkitMediaStream([track]);
|
||||
// stream found, stop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (session && electedStream) {
|
||||
console.info('Switching simulcast substream.');
|
||||
console.info([esl, primarySSRC, msid, session, electedStream]);
|
||||
|
||||
var msidParts = msid.split(' ');
|
||||
var selRemoteVideo = $(['#', 'remoteVideo_', session.sid, '_', msidParts[0]].join(''));
|
||||
|
||||
var updateLargeVideo = (ssrc2jid[videoSrcToSsrc[selRemoteVideo.attr('src')]]
|
||||
== ssrc2jid[videoSrcToSsrc[$('#largeVideo').attr('src')]]);
|
||||
var updateFocusedVideoSrc = (selRemoteVideo.attr('src') == focusedVideoSrc);
|
||||
|
||||
var electedStreamUrl = webkitURL.createObjectURL(electedStream);
|
||||
selRemoteVideo.attr('src', electedStreamUrl);
|
||||
videoSrcToSsrc[selRemoteVideo.attr('src')] = primarySSRC;
|
||||
|
||||
if (updateLargeVideo) {
|
||||
VideoLayout.updateLargeVideo(electedStreamUrl);
|
||||
}
|
||||
|
||||
if (updateFocusedVideoSrc) {
|
||||
focusedVideoSrc = electedStreamUrl;
|
||||
}
|
||||
|
||||
} else {
|
||||
console.error('Could not find a stream or a session.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return my;
|
||||
}(VideoLayout || {}));
|
||||
|
|