A lot of updates :)

This commit is contained in:
WolverinDEV 2018-03-07 19:06:52 +01:00
parent 53ac57c3b4
commit 3675aa98e6
72 changed files with 100327 additions and 99467 deletions

2
.idea/Web-Client.iml generated
View file

@ -4,5 +4,7 @@
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="adapter-latest" level="application" />
<orderEntry type="library" name="jquery.tmpl" level="application" />
</component>
</module>

7
.idea/dictionaries/wolverindev.xml generated Normal file
View file

@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="wolverindev">
<words>
<w>resampler</w>
</words>
</dictionary>
</component>

View file

@ -0,0 +1,34 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="display" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="10">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
<item index="6" class="java.lang.String" itemvalue="x-tab" />
<item index="7" class="java.lang.String" itemvalue="x-entry" />
<item index="8" class="java.lang.String" itemvalue="x-content" />
<item index="9" class="java.lang.String" itemvalue="x-tag" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
</profile>
</component>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="PROJECT" libraries="{adapter-latest, jquery.tmpl}" />
<includedPredefinedLibrary name="Node.js Core" />
<excludedPredefinedLibrary name="HTML" />
</component>

751
.idea/workspace.xml generated
View file

@ -1,7 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="978d055d-27d3-431a-bd34-e5e79bb273b3" name="Default" comment="" />
<list default="true" id="978d055d-27d3-431a-bd34-e5e79bb273b3" name="Default" comment="">
<change beforePath="" afterPath="$PROJECT_DIR$/.idea/dictionaries/wolverindev.xml" />
<change beforePath="" afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/ui/modal/ModalConnect.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/ui/modal/ModalCreateChannel.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/ui/modal/ModalSettings.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/voice/AudioController.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/voice/AudioResampler.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/voice/VoiceHandler.js.map" />
<change beforePath="" afterPath="$PROJECT_DIR$/js/voice/VoiceRecorder.ts" />
<change beforePath="$PROJECT_DIR$/.idea/Web-Client.iml" afterPath="$PROJECT_DIR$/.idea/Web-Client.iml" />
<change beforePath="$PROJECT_DIR$/.idea/jsLibraryMappings.xml" afterPath="$PROJECT_DIR$/.idea/jsLibraryMappings.xml" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
<change beforePath="$PROJECT_DIR$/asm/generated/TeaWeb-Native.js" afterPath="$PROJECT_DIR$/asm/generated/TeaWeb-Native.js" />
<change beforePath="$PROJECT_DIR$/asm/generated/libopus.js" afterPath="$PROJECT_DIR$/asm/generated/libopus.js" />
<change beforePath="$PROJECT_DIR$/asm/src/WebASMTest.cpp" afterPath="$PROJECT_DIR$/asm/src/WebASMTest.cpp" />
<change beforePath="$PROJECT_DIR$/css/general.css" afterPath="$PROJECT_DIR$/css/general.css" />
<change beforePath="$PROJECT_DIR$/css/ts/icons.css" afterPath="$PROJECT_DIR$/css/ts/icons.css" />
<change beforePath="$PROJECT_DIR$/css/ts/tab.css" afterPath="$PROJECT_DIR$/css/ts/tab.css" />
<change beforePath="$PROJECT_DIR$/index.html" afterPath="$PROJECT_DIR$/index.html" />
<change beforePath="$PROJECT_DIR$/js/FileManager.js" afterPath="$PROJECT_DIR$/js/FileManager.js" />
<change beforePath="$PROJECT_DIR$/js/FileManager.js.map" afterPath="$PROJECT_DIR$/js/FileManager.js.map" />
<change beforePath="$PROJECT_DIR$/js/FileManager.ts" afterPath="$PROJECT_DIR$/js/FileManager.ts" />
<change beforePath="$PROJECT_DIR$/js/InfoBar.js" afterPath="$PROJECT_DIR$/js/InfoBar.js" />
<change beforePath="$PROJECT_DIR$/js/InfoBar.js.map" afterPath="$PROJECT_DIR$/js/InfoBar.js.map" />
<change beforePath="$PROJECT_DIR$/js/InfoBar.ts" afterPath="$PROJECT_DIR$/js/InfoBar.ts" />
<change beforePath="$PROJECT_DIR$/js/client.js" afterPath="$PROJECT_DIR$/js/client.js" />
<change beforePath="$PROJECT_DIR$/js/client.js.map" afterPath="$PROJECT_DIR$/js/client.js.map" />
<change beforePath="$PROJECT_DIR$/js/client.ts" afterPath="$PROJECT_DIR$/js/client.ts" />
<change beforePath="$PROJECT_DIR$/js/codec/Codec.js" afterPath="$PROJECT_DIR$/js/codec/Codec.js" />
<change beforePath="$PROJECT_DIR$/js/codec/Codec.js.map" afterPath="$PROJECT_DIR$/js/codec/Codec.js.map" />
<change beforePath="$PROJECT_DIR$/js/codec/Codec.ts" afterPath="$PROJECT_DIR$/js/codec/Codec.ts" />
<change beforePath="$PROJECT_DIR$/js/connection.js" afterPath="$PROJECT_DIR$/js/connection.js" />
<change beforePath="$PROJECT_DIR$/js/connection.js.map" afterPath="$PROJECT_DIR$/js/connection.js.map" />
<change beforePath="$PROJECT_DIR$/js/connection.ts" afterPath="$PROJECT_DIR$/js/connection.ts" />
<change beforePath="$PROJECT_DIR$/js/contextMenu.js" afterPath="$PROJECT_DIR$/js/contextMenu.js" />
<change beforePath="$PROJECT_DIR$/js/contextMenu.js.map" afterPath="$PROJECT_DIR$/js/contextMenu.js.map" />
<change beforePath="$PROJECT_DIR$/js/contextMenu.ts" afterPath="$PROJECT_DIR$/js/contextMenu.ts" />
<change beforePath="$PROJECT_DIR$/js/main.js" afterPath="$PROJECT_DIR$/js/main.js" />
<change beforePath="$PROJECT_DIR$/js/main.js.map" afterPath="$PROJECT_DIR$/js/main.js.map" />
<change beforePath="$PROJECT_DIR$/js/main.ts" afterPath="$PROJECT_DIR$/js/main.ts" />
<change beforePath="$PROJECT_DIR$/js/settings.js" afterPath="$PROJECT_DIR$/js/settings.js" />
<change beforePath="$PROJECT_DIR$/js/settings.js.map" afterPath="$PROJECT_DIR$/js/settings.js.map" />
<change beforePath="$PROJECT_DIR$/js/settings.ts" afterPath="$PROJECT_DIR$/js/settings.ts" />
<change beforePath="$PROJECT_DIR$/js/ui/ControlBar.js" afterPath="$PROJECT_DIR$/js/ui/ControlBar.js" />
<change beforePath="$PROJECT_DIR$/js/ui/ControlBar.js.map" afterPath="$PROJECT_DIR$/js/ui/ControlBar.js.map" />
<change beforePath="$PROJECT_DIR$/js/ui/ControlBar.ts" afterPath="$PROJECT_DIR$/js/ui/ControlBar.ts" />
<change beforePath="$PROJECT_DIR$/js/ui/channel.js" afterPath="$PROJECT_DIR$/js/ui/channel.js" />
<change beforePath="$PROJECT_DIR$/js/ui/channel.js.map" afterPath="$PROJECT_DIR$/js/ui/channel.js.map" />
<change beforePath="$PROJECT_DIR$/js/ui/channel.ts" afterPath="$PROJECT_DIR$/js/ui/channel.ts" />
<change beforePath="$PROJECT_DIR$/js/ui/client.js" afterPath="$PROJECT_DIR$/js/ui/client.js" />
<change beforePath="$PROJECT_DIR$/js/ui/client.js.map" afterPath="$PROJECT_DIR$/js/ui/client.js.map" />
<change beforePath="$PROJECT_DIR$/js/ui/client.ts" afterPath="$PROJECT_DIR$/js/ui/client.ts" />
<change beforePath="$PROJECT_DIR$/js/ui/server.js" afterPath="$PROJECT_DIR$/js/ui/server.js" />
<change beforePath="$PROJECT_DIR$/js/ui/server.js.map" afterPath="$PROJECT_DIR$/js/ui/server.js.map" />
<change beforePath="$PROJECT_DIR$/js/ui/server.ts" afterPath="$PROJECT_DIR$/js/ui/server.ts" />
<change beforePath="$PROJECT_DIR$/js/ui/view.js" afterPath="$PROJECT_DIR$/js/ui/view.js" />
<change beforePath="$PROJECT_DIR$/js/ui/view.js.map" afterPath="$PROJECT_DIR$/js/ui/view.js.map" />
<change beforePath="$PROJECT_DIR$/js/ui/view.ts" afterPath="$PROJECT_DIR$/js/ui/view.ts" />
<change beforePath="$PROJECT_DIR$/js/utils/modal.js" afterPath="$PROJECT_DIR$/js/utils/modal.js" />
<change beforePath="$PROJECT_DIR$/js/utils/modal.js.map" afterPath="$PROJECT_DIR$/js/utils/modal.js.map" />
<change beforePath="$PROJECT_DIR$/js/utils/modal.ts" afterPath="$PROJECT_DIR$/js/utils/modal.ts" />
<change beforePath="$PROJECT_DIR$/js/utils/tab.js" afterPath="$PROJECT_DIR$/js/utils/tab.js" />
<change beforePath="$PROJECT_DIR$/js/utils/tab.js.map" afterPath="$PROJECT_DIR$/js/utils/tab.js.map" />
<change beforePath="$PROJECT_DIR$/js/utils/tab.ts" afterPath="$PROJECT_DIR$/js/utils/tab.ts" />
<change beforePath="$PROJECT_DIR$/js/voice.js" afterPath="$PROJECT_DIR$/js/voice/VoiceHandler.js" />
<change beforePath="$PROJECT_DIR$/js/voice.js.map" afterPath="" />
<change beforePath="$PROJECT_DIR$/js/voice.ts" afterPath="$PROJECT_DIR$/js/voice/VoiceHandler.ts" />
<change beforePath="$PROJECT_DIR$/vendor/aurora/aurora.js" afterPath="$PROJECT_DIR$/vendor/aurora/aurora.js" />
<change beforePath="$PROJECT_DIR$/vendor/bootstrap/js/bootstrap.bundle.js" afterPath="$PROJECT_DIR$/vendor/bootstrap/js/bootstrap.bundle.js" />
<change beforePath="$PROJECT_DIR$/vendor/opus/opus_to_pcm.js" afterPath="$PROJECT_DIR$/vendor/opus/opus_to_pcm.js" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
@ -11,24 +82,44 @@
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="Codec.ts" pinned="false" current-in-tab="true">
<file leaf-file-name="Codec.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/codec/Codec.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="198">
<caret line="14" column="35" lean-forward="true" selection-start-line="14" selection-start-column="35" selection-end-line="14" selection-end-column="35" />
<state relative-caret-position="501">
<caret line="204" column="34" lean-forward="true" selection-start-line="204" selection-start-column="34" selection-end-line="204" selection-end-column="34" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="VoiceHandler.ts" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/js/voice/VoiceHandler.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1506">
<caret line="48" column="43" lean-forward="false" selection-start-line="48" selection-start-column="43" selection-end-line="48" selection-end-column="43" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="client.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/client.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
<state relative-caret-position="267">
<caret line="117" column="42" lean-forward="true" selection-start-line="117" selection-start-column="42" selection-end-line="117" selection-end-column="42" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ModalSettings.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/ui/modal/ModalSettings.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-198">
<caret line="12" column="31" lean-forward="false" selection-start-line="12" selection-start-column="23" selection-end-line="12" selection-end-column="31" />
<folding />
</state>
</provider>
</entry>
@ -36,8 +127,8 @@
<file leaf-file-name="connection.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/connection.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="612">
<caret line="34" column="24" lean-forward="true" selection-start-line="34" selection-start-column="24" selection-end-line="34" selection-end-column="24" />
<state relative-caret-position="408">
<caret line="302" column="36" lean-forward="false" selection-start-line="302" selection-start-column="24" selection-end-line="302" selection-end-column="36" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
@ -45,83 +136,86 @@
</provider>
</entry>
</file>
<file leaf-file-name="index.d.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/node_modules/@types/emscripten/index.d.ts">
<file leaf-file-name="channel.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/ui/channel.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1764">
<caret line="103" column="13" lean-forward="false" selection-start-line="103" selection-start-column="13" selection-end-line="103" selection-end-column="13" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="lib.es6.d.ts" pinned="false" current-in-tab="false">
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="647">
<caret line="7148" column="4" lean-forward="false" selection-start-line="7148" selection-start-column="4" selection-end-line="7148" selection-end-column="4" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="settings.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/settings.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="encoder.js" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/vendor/libopus.js/lib/encoder.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3294">
<caret line="183" column="13" lean-forward="false" selection-start-line="183" selection-start-column="13" selection-end-line="183" selection-end-column="13" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="voice.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/voice.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="594">
<caret line="51" column="10" lean-forward="false" selection-start-line="51" selection-start-column="10" selection-end-line="51" selection-end-column="10" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="client.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/ui/client.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="324">
<caret line="18" column="25" lean-forward="false" selection-start-line="18" selection-start-column="25" selection-end-line="18" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="chat.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/chat.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="513">
<caret line="32" column="41" lean-forward="false" selection-start-line="32" selection-start-column="41" selection-end-line="32" selection-end-column="41" />
<state relative-caret-position="263">
<caret line="278" column="50" lean-forward="false" selection-start-line="278" selection-start-column="46" selection-end-line="278" selection-end-column="50" />
<folding>
<marker date="1519748729173" expanded="true" signature="1975:1985" ph="..." />
<marker date="1520366277688" expanded="true" signature="3766:3823" ph="..." />
<marker date="1520366277688" expanded="true" signature="3897:3954" ph="..." />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="main.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/main.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="234">
<caret line="16" column="24" lean-forward="true" selection-start-line="16" selection-start-column="24" selection-end-line="16" selection-end-column="24" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="InfoBar.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/InfoBar.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-262">
<caret line="57" column="25" lean-forward="false" selection-start-line="57" selection-start-column="25" selection-end-line="57" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="index.html" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-90">
<caret line="28" column="87" lean-forward="true" selection-start-line="28" selection-start-column="87" selection-end-line="28" selection-end-column="87" />
<folding>
<element signature="n#style#0;n#div#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#div#1;n#div#0;n#div#1;n#div#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#div#0;n#x-content#0;n#x-entry#0;n#x-tab#0;n#template#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#div#0;n#div#0;n#x-content#0;n#x-entry#0;n#x-tab#0;n#template#0;n#body#0;n#html#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="VoiceRecorder.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/js/voice/VoiceRecorder.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="192">
<caret line="15" column="11" lean-forward="false" selection-start-line="15" selection-start-column="4" selection-end-line="15" selection-end-column="11" />
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="TypeScript File" />
</list>
</option>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>createBuffer</find>
<find>console.log</find>
<find>on_encoded_data</find>
<find>handleVoiceData</find>
<find>vad_ppt_key</find>
<find>vat_ppt_key</find>
<find>start</find>
<find>channelTree</find>
<find>channel</find>
<find>update</find>
<find>on_connected</find>
<find>on_data</find>
</findStrings>
</component>
@ -132,8 +226,36 @@
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/js/main.js" />
<option value="$PROJECT_DIR$/js/codec/Codec.ts" />
<option value="$PROJECT_DIR$/js/contextMenu.ts" />
<option value="$PROJECT_DIR$/vendor/bootstrap/js/bootstrap.bundle.js" />
<option value="$PROJECT_DIR$/js/voice.ts" />
<option value="$PROJECT_DIR$/js/voice/AudioResampler.ts" />
<option value="$PROJECT_DIR$/js/voice/VoiceRecoder.ts" />
<option value="$PROJECT_DIR$/js/main.ts" />
<option value="$PROJECT_DIR$/js/utils/modal.ts" />
<option value="$PROJECT_DIR$/css/ts/tab.css" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalSettings.ts" />
<option value="$PROJECT_DIR$/css/ts/client.css" />
<option value="$PROJECT_DIR$/js/ui/ControlBar.ts" />
<option value="$PROJECT_DIR$/js/voice/VoiceRecorder.ts" />
<option value="$PROJECT_DIR$/js/voice/AudioController.ts" />
<option value="$PROJECT_DIR$/js/ui/server.ts" />
<option value="$PROJECT_DIR$/js/ui/view.ts" />
<option value="$PROJECT_DIR$/js/settings.ts" />
<option value="$PROJECT_DIR$/js/utils/tab.ts" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalConnect.ts" />
<option value="$PROJECT_DIR$/js/ui/channel.ts" />
<option value="$PROJECT_DIR$/js/ui/client.ts" />
<option value="$PROJECT_DIR$/css/ts/icons.css" />
<option value="$PROJECT_DIR$/js/FileManager.ts" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalCreateChannel.ts" />
<option value="$PROJECT_DIR$/js/connection.ts" />
<option value="$PROJECT_DIR$/css/general.css" />
<option value="$PROJECT_DIR$/index.html" />
<option value="$PROJECT_DIR$/js/client.ts" />
<option value="$PROJECT_DIR$/js/InfoBar.ts" />
<option value="$PROJECT_DIR$/js/codec/Codec.ts" />
<option value="$PROJECT_DIR$/js/voice/VoiceHandler.ts" />
</list>
</option>
</component>
@ -150,10 +272,10 @@
</component>
<component name="PhpWorkspaceProjectConfiguration" backward_compatibility_performed="true" />
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="65" />
<option name="x" value="63" />
<option name="y" value="-4" />
<option name="width" value="1855" />
<option name="height" value="1084" />
<option name="width" value="1215" />
<option name="height" value="896" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
@ -177,6 +299,39 @@
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="asm" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="asm" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="generated" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="asm" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="src" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="css" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="css" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="ts" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="img" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
@ -200,12 +355,25 @@
<item name="js" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="ui" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="js" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="ui" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="modal" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="js" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="utils" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
<path>
<item name="Web-Client" type="b2602c69:ProjectViewProjectNode" />
<item name="Web-Client" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="js" type="2a2b976b:PhpTreeStructureProvider$1" />
<item name="voice" type="2a2b976b:PhpTreeStructureProvider$1" />
</path>
</expand>
<select />
</subPane>
@ -216,11 +384,16 @@
</component>
<component name="PropertiesComponent">
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="settings.editor.selected.configurable" value="settings.typescriptcompiler" />
<property name="settings.editor.selected.configurable" value="preferences.keymap" />
<property name="javascript.nodejs.core.library.configured.version" value="4.2.6" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/js/voice" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
@ -248,33 +421,34 @@
<updated>1519749313999</updated>
<workItem from="1519749316100" duration="9698000" />
<workItem from="1520012895408" duration="13944000" />
<workItem from="1520175420796" duration="52205000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="23642000" />
<option name="totallyTimeSpent" value="75847000" />
</component>
<component name="ToolWindowManager">
<frame x="65" y="-4" width="1855" height="1084" extended-state="6" />
<editor active="true" />
<frame x="65" y="-4" width="1215" height="1028" extended-state="6" />
<layout>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="npm" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="TypeScript" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.49973047" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.49973047" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="TypeScript" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2483731" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.23045267" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.14320987" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Inspection Results" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.329718" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.329718" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
@ -303,8 +477,6 @@
<option value="$PROJECT_DIR$/js/InfoBar.js.map" />
<option value="$PROJECT_DIR$/js/chat.js" />
<option value="$PROJECT_DIR$/js/chat.js.map" />
<option value="$PROJECT_DIR$/js/voice.js" />
<option value="$PROJECT_DIR$/js/voice.js.map" />
<option value="$PROJECT_DIR$/js/main.js" />
<option value="$PROJECT_DIR$/js/main.js.map" />
<option value="$PROJECT_DIR$/js/proto.js" />
@ -325,6 +497,16 @@
<option value="$PROJECT_DIR$/js/permission/PermissionManager.js.map" />
<option value="$PROJECT_DIR$/js/permission/GroupManager.js" />
<option value="$PROJECT_DIR$/js/permission/GroupManager.js.map" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalConnect.js.map" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalConnect.js" />
<option value="$PROJECT_DIR$/js/voice/AudioResampler.js.map" />
<option value="$PROJECT_DIR$/js/voice/AudioController.js" />
<option value="$PROJECT_DIR$/js/voice/AudioResampler.js" />
<option value="$PROJECT_DIR$/js/voice/AudioController.js.map" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalCreateChannel.js.map" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalCreateChannel.js" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalSettings.js.map" />
<option value="$PROJECT_DIR$/js/ui/modal/ModalSettings.js" />
</list>
</option>
</component>
@ -333,39 +515,11 @@
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<option name="time" value="1" />
<option name="time" value="3" />
</breakpoint-manager>
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2898">
<caret line="161" column="19" lean-forward="false" selection-start-line="161" selection-start-column="19" selection-end-line="161" selection-end-column="19" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/main.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="7" column="0" lean-forward="false" selection-start-line="7" selection-start-column="0" selection-end-line="7" selection-end-column="0" />
<folding>
<element signature="n#!!doc" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/client.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/connection.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
@ -392,19 +546,14 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/libopus.js/lib/encoder.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3294">
<caret line="183" column="13" lean-forward="false" selection-start-line="183" selection-start-column="13" selection-end-line="183" selection-end-column="13" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice.ts">
<entry file="file://$PROJECT_DIR$/vendor/libopus.js/lib/encoder.js" />
<entry file="file://$PROJECT_DIR$/js/voice/VoiceHandler.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1818">
<caret line="101" column="40" lean-forward="true" selection-start-line="101" selection-start-column="40" selection-end-line="101" selection-end-column="40" />
<folding />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
@ -428,9 +577,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="7" column="0" lean-forward="false" selection-start-line="7" selection-start-column="0" selection-end-line="7" selection-end-column="0" />
<folding>
<element signature="n#!!doc" expanded="false" />
</folding>
</state>
</provider>
</entry>
@ -442,14 +588,7 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2898">
<caret line="161" column="19" lean-forward="false" selection-start-line="161" selection-start-column="19" selection-end-line="161" selection-end-column="19" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/libopus.js/lib/encoder.js" />
<entry file="file://$PROJECT_DIR$/node_modules/@types/emscripten/index.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1764">
@ -458,83 +597,339 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/client.ts">
<entry file="file://$PROJECT_DIR$/vendor/bootstrap/js/bootstrap.bundle.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/vendor/libopus.js/lib/encoder.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3294">
<caret line="183" column="13" lean-forward="false" selection-start-line="183" selection-start-column="13" selection-end-line="183" selection-end-column="13" />
<state relative-caret-position="286">
<caret line="4727" column="20" lean-forward="false" selection-start-line="4727" selection-start-column="20" selection-end-line="4727" selection-end-column="20" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/settings.ts">
<entry file="file://$PROJECT_DIR$/vendor/bootstrap/js/bootstrap.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/client.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="324">
<caret line="18" column="25" lean-forward="false" selection-start-line="18" selection-start-column="25" selection-end-line="18" selection-end-column="25" />
<state relative-caret-position="188">
<caret line="2288" column="20" lean-forward="false" selection-start-line="2288" selection-start-column="20" selection-end-line="2288" selection-end-column="20" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/chat.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="513">
<state relative-caret-position="576">
<caret line="32" column="41" lean-forward="false" selection-start-line="32" selection-start-column="41" selection-end-line="32" selection-end-column="41" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/modal/ModalConnect.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/modal/ModalConnect.js.map">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
<provider editor-type-id="sourcemapFileViewerProvider">
<state />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice/AudioResampler.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="378">
<caret line="21" column="1" lean-forward="false" selection-start-line="21" selection-start-column="1" selection-end-line="21" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/node_modules/@types/jquery/index.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180">
<caret line="34" column="20" lean-forward="false" selection-start-line="34" selection-start-column="14" selection-end-line="34" selection-end-column="20" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/contextMenu.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="188">
<caret line="12" column="0" lean-forward="false" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="269">
<caret line="7190" column="10" lean-forward="false" selection-start-line="7190" selection-start-column="10" selection-end-line="7190" selection-end-column="10" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice/AudioController.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="522">
<caret line="29" column="31" lean-forward="true" selection-start-line="29" selection-start-column="31" selection-end-line="29" selection-end-column="31" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/server.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="341">
<caret line="30" column="33" lean-forward="false" selection-start-line="30" selection-start-column="33" selection-end-line="30" selection-end-column="33" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/view.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="270">
<caret line="20" column="18" lean-forward="false" selection-start-line="20" selection-start-column="4" selection-end-line="20" selection-end-column="18" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/utils/tab.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="316">
<caret line="47" column="59" lean-forward="false" selection-start-line="47" selection-start-column="59" selection-end-line="47" selection-end-column="59" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/client.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="234">
<caret line="175" column="0" lean-forward="false" selection-start-line="175" selection-start-column="0" selection-end-line="175" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/settings.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="690">
<caret line="72" column="0" lean-forward="false" selection-start-line="72" selection-start-column="0" selection-end-line="72" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice/AudioController.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-795">
<caret line="4" column="60" lean-forward="false" selection-start-line="4" selection-start-column="60" selection-end-line="4" selection-end-column="60" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/ControlBar.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="204">
<caret line="29" column="38" lean-forward="true" selection-start-line="29" selection-start-column="38" selection-end-line="29" selection-end-column="38" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/permission/GroupManager.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="33">
<caret line="78" column="29" lean-forward="false" selection-start-line="78" selection-start-column="12" selection-end-line="78" selection-end-column="29" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/permission/PermissionManager.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1825">
<caret line="242" column="42" lean-forward="true" selection-start-line="242" selection-start-column="42" selection-end-line="242" selection-end-column="42" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/utils/modal.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="108">
<caret line="6" column="21" lean-forward="false" selection-start-line="6" selection-start-column="21" selection-end-line="6" selection-end-column="21" />
<folding>
<marker date="1519748729173" expanded="true" signature="1975:1985" ph="..." />
<marker date="1520348245429" expanded="true" signature="2079:2086" ph="×" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/css/ts/client.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1026">
<caret line="12" column="0" lean-forward="true" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/img/client_icon_sprite.svg">
<provider selected="true" editor-type-id="images">
<state />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/FileManager.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="213">
<caret line="303" column="62" lean-forward="true" selection-start-line="303" selection-start-column="62" selection-end-line="303" selection-end-column="62" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/modal/ModalConnect.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-756">
<caret line="6" column="6" lean-forward="true" selection-start-line="6" selection-start-column="6" selection-end-line="7" selection-end-column="30" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/modal/ModalCreateChannel.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="234">
<caret line="13" column="0" lean-forward="false" selection-start-line="13" selection-start-column="0" selection-end-line="13" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/asm/generated/TeaWeb-Native.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="342">
<caret line="48" column="21" lean-forward="false" selection-start-line="48" selection-start-column="21" selection-end-line="48" selection-end-column="21" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/asm/src/WebASMTest.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="144">
<caret line="8" column="39" lean-forward="false" selection-start-line="8" selection-start-column="39" selection-end-line="8" selection-end-column="39" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/css/ts/tab.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="186">
<caret line="34" column="0" lean-forward="true" selection-start-line="34" selection-start-column="0" selection-end-line="34" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/css/ts/icons.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="198">
<caret line="11" column="1" lean-forward="false" selection-start-line="11" selection-start-column="1" selection-end-line="11" selection-end-column="1" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/css/general.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="429">
<caret line="103" column="0" lean-forward="true" selection-start-line="103" selection-start-column="0" selection-end-line="103" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/modal/ModalSettings.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-198">
<caret line="12" column="31" lean-forward="false" selection-start-line="12" selection-start-column="23" selection-end-line="12" selection-end-column="31" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/ui/channel.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="263">
<caret line="278" column="50" lean-forward="false" selection-start-line="278" selection-start-column="46" selection-end-line="278" selection-end-column="50" />
<folding>
<marker date="1520366277688" expanded="true" signature="3766:3823" ph="..." />
<marker date="1520366277688" expanded="true" signature="3897:3954" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/connection.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="612">
<caret line="34" column="24" lean-forward="true" selection-start-line="34" selection-start-column="24" selection-end-line="34" selection-end-column="24" />
<state relative-caret-position="408">
<caret line="302" column="36" lean-forward="false" selection-start-line="302" selection-start-column="24" selection-end-line="302" selection-end-column="36" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
<entry file="file://$PROJECT_DIR$/js/client.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="647">
<caret line="7148" column="4" lean-forward="false" selection-start-line="7148" selection-start-column="4" selection-end-line="7148" selection-end-column="4" />
<state relative-caret-position="267">
<caret line="117" column="42" lean-forward="true" selection-start-line="117" selection-start-column="42" selection-end-line="117" selection-end-column="42" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice.ts">
<entry file="file://$PROJECT_DIR$/js/InfoBar.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="594">
<caret line="51" column="10" lean-forward="false" selection-start-line="51" selection-start-column="10" selection-end-line="51" selection-end-column="10" />
<state relative-caret-position="-262">
<caret line="57" column="25" lean-forward="false" selection-start-line="57" selection-start-column="25" selection-end-line="57" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-90">
<caret line="28" column="87" lean-forward="true" selection-start-line="28" selection-start-column="87" selection-end-line="28" selection-end-column="87" />
<folding>
<element signature="n#style#0;n#div#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#div#1;n#div#0;n#div#1;n#div#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#div#0;n#x-content#0;n#x-entry#0;n#x-tab#0;n#template#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#div#0;n#div#0;n#x-content#0;n#x-entry#0;n#x-tab#0;n#template#0;n#body#0;n#html#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice/VoiceRecorder.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="192">
<caret line="15" column="11" lean-forward="false" selection-start-line="15" selection-start-column="4" selection-end-line="15" selection-end-column="11" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/codec/Codec.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="198">
<caret line="14" column="35" lean-forward="true" selection-start-line="14" selection-start-column="35" selection-end-line="14" selection-end-column="35" />
<state relative-caret-position="501">
<caret line="204" column="34" lean-forward="true" selection-start-line="204" selection-start-column="34" selection-end-line="204" selection-end-column="34" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/main.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="234">
<caret line="16" column="24" lean-forward="true" selection-start-line="16" selection-start-column="24" selection-end-line="16" selection-end-column="24" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/js/voice/VoiceHandler.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1506">
<caret line="48" column="43" lean-forward="false" selection-start-line="48" selection-start-column="43" selection-end-line="48" selection-end-column="43" />
<folding>
<element signature="n#!!doc" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -12,14 +12,14 @@ extern "C" {
};
EMSCRIPTEN_KEEPALIVE
OpusHandle* codec_opus_createNativeHandle(size_t channelCount) {
printf("inizalisized (%d)!\n", channelCount);
auto codec = new OpusHandle;
OpusHandle* codec_opus_createNativeHandle(size_t channelCount, int type) {
printf("Inizalisize opus. (Channel count: %d Sample rate: %d Type: %d)!\n", channelCount, 48000, type);
auto codec = new OpusHandle{};
int error = 0;
codec->decoder = opus_decoder_create(48000, channelCount, &error);
printf("Status %d\n", error);
codec->encoder = opus_encoder_create(48000, channelCount, OPUS_APPLICATION_AUDIO, &error);
printf("Status %d\n", error);
codec->encoder = opus_encoder_create(48000, channelCount, type, &error);
printf("Status %d Channel %d\n", error, codec->channelCount);
return codec;
}
@ -38,7 +38,6 @@ extern "C" {
EMSCRIPTEN_KEEPALIVE
int codec_opus_encode(OpusHandle* handle, uint8_t* buffer, size_t length, size_t maxLength) {
printf("codec_opus_encode(%p,%p,%d, %d)\n", handle->encoder, (void*) buffer, length, maxLength);
auto result = opus_encode_float(handle->encoder, (float*) buffer, length / handle->channelCount, buffer, maxLength);
if(result < 0) return result;
return result;

View file

@ -106,10 +106,10 @@
}
/* Modal Body */
.modal-body {padding: 2px 16px;}
.modal-body:not(:empty) {padding: 2px 16px;}
/* Modal Footer */
.modal-footer {
.modal-footer:not(:empty) {
padding: 2px 16px;
}
@ -132,7 +132,7 @@
}
/* Modal Content */
.modal-content {
.modal-content:not(:empty) {
position: absolute;
display: inline-flex;
flex-direction: column;
@ -240,4 +240,10 @@ html {
background-color: rgba(0,0,0,0.4);
border: rgba(255,255,255,.75) solid;
border-width: 2px;
}
.GroupBox {
border: gray solid;
border-width: 2px;
border-radius: 0px 6px 6px 6px;
}

View file

@ -925,7 +925,7 @@
background-position: calc(-128px * 2) calc(-192px * 2);
}
.icon_x32.client-message_info {
background-position: calc(-160px * 2) calc(-192px * 2);
background-position: calc(-160px * 2)pe the key you wish calc(-192px * 2);
}
.icon_x32.client-message_outgoing {
background-position: calc(-192px * 2) calc(-192px * 2);
@ -966,7 +966,7 @@
.icon_x32.client-permission_overview {
background-position: calc(-64px * 2) calc(-224px * 2);
}
.icon_x32.client-permission_server_groups {
.icon_x32.client-permission_server_groups pe the key you wish{
background-position: calc(-96px * 2) calc(-224px * 2);
}
.icon_x32.client-phoneticsnickname {
@ -1028,7 +1028,7 @@
}
.icon_x32.client-refresh {
background-position: calc(-224px * 2) calc(-256px * 2);
}
}pe the key you wish
.icon_x32.client-register {
background-position: calc(-256px * 2) calc(-256px * 2);
}

View file

@ -37,7 +37,6 @@ x-tab { display:none }
max-width: 100%;
overflow: auto;
/*height: 24px;*/
overflow: auto;
overflow-y: hidden;
white-space: nowrap;
margin-bottom: -1px;
@ -59,6 +58,10 @@ x-tab { display:none }
cursor: pointer;
}
.tab .tab-content-invisible {
display: none;
}
.tab .selected {
background: #11111111!important;
}

View file

@ -13,20 +13,22 @@
<body>
TeaSpeak-Web<br>
<div style="width: 1200px; height: 1050px; display: flex; flex-direction: column; resize: both; margin: 20px"> <!-- Container -->
<div style="width: 600px; height: 450px; display: flex; flex-direction: column; resize: both; margin: 20px"> <!-- Container -->
<div style="height: 45px; width: 100%; border-radius: 2px 0px 0px 0px; border-bottom-width: 0px; background-color: lightgrey" class="main_container">
<div id="control_bar" class="control_bar">
<div class="button btn_connect"><div class="icon_x32 client-connect"></div></div>
<div style="border-left:2px solid gray;height: auto; margin-left: 5px; margin-right: 5px"></div>
<div class="button btn_client_away"><div class="icon_x32 client-away"></div></div>
<div class="button btn_mute_input"><div class="icon_x32 client-input_muted"></div></div>
<div class="button btn_mute_output"><div class="icon_x32 client-output_muted"></div></div>
<div style="width: 100%"></div>
<div class="button"><div class="icon_x32 client-settings"></div></div>
<div class="button btn_open_settings"><div class="icon_x32 client-settings"></div></div>
</div>
</div>
<div style="flex-direction: row; height: 100%; width: 100%; display: flex">
<div style="width: 60%; flex-direction: column;">
<div style="height: 60%; border-radius: 0px 0px 0px 0px; border-right-width: 0px;" class="main_container">
<div style="height: 60%; border-radius: 0px 0px 0px 0px; border-right-width: 0px; overflow: auto; overflow-x: visible" class="main_container">
<div class="channelTree" id="channelTree">
<div class="server l"><div class="icon client-server_green"></div> TeaSpeak web!</div>
</div>
@ -102,7 +104,6 @@
</div>
</div>
</div>
</x-content>
</x-entry>
<x-entry>
@ -160,6 +161,48 @@
</div>
</div>
</template>
<template id="tmpl_settings">
<x-tab>
<x-entry>
<x-tag>General</x-tag>
<x-content>Didnt setuped yet!</x-content>
</x-entry>
<x-entry>
<x-tag>Voice</x-tag>
<x-content>
<div style="display: flex; flex-direction: row; width: 100%; justify-content: space-evenly" class="settings_voice">
<div style="vertical-align: center; margin: 20px; min-width: 175px">
<a>Voice Activity Detection</a>
<div>
<fieldset class="GroupBox">
<div><input type="radio" name="vad_type" value="pt" display="Always active"> Always active</div>
<div><input type="radio" name="vad_type" value="vad" display="Voice activity detection"> Voice activity detection</div>
<div><input type="radio" name="vad_type" value="ppt" display="Push to talk"> Push to talk</div>
</fieldset>
</div>
</div>
<div style="border-left:1px solid #000;height: auto;"></div>
<div style="flex-direction: column; align-content: stretch; vertical-align: center; margin: 20px;">
<div class="vad_settings">
<div style="font-size: 14px; text-align: center"><a class="vad_type">Type[Unknown]</a> settings</div>
<div class="vad_type_settings vad_type_pt">There are no setting entries for an <b>always</b> online voice detection.</div>
<div class="vad_type_settings vad_type_ppt">
<a>Push to talk key:</a>
<button class="vat_ppt_key">Uninitialised</button>
</div>
<div class="vad_type_settings vad_type_vad">
<a>Voice activity threshold</a>
<div class="vad_threshold_selector">
<input type="range" min="0" max="100" value="50" class="vad_slider">
</div>
</div>
</div>
</div>
</div>
</x-content>
</x-entry>
</x-tab>
</template>
<script src="vendor/jquery/jquery.min.js"></script>
<!--
@ -173,6 +216,9 @@
<script src="vendor/aurora/aurora.js"></script>
<script src="js/utils/modal.js"></script>
<script src="js/ui/modal/ModalConnect.js"></script>
<script src="js/ui/modal/ModalSettings.js"></script>
<script src="js/ui/modal/ModalCreateChannel.js"></script>
<script src="js/utils/tab.js"></script>
<script src="js/proto.js"></script>
@ -180,11 +226,16 @@
<script src="js/contextMenu.js"></script>
<script src="js/connection.js"></script>
<script src="js/FileManager.js"></script>
<script src="js/voice.js"></script>
<script src="js/client.js"></script>
<script src="js/chat.js"></script>
<script src="js/InfoBar.js"></script>
<script src="js/voice/VoiceHandler.js"></script>
<script src="js/voice/VoiceRecorder.js"></script>
<script src="js/voice/AudioResampler.js"></script>
<script src="js/voice/AudioController.js"></script>
<script src="js/permission/PermissionManager.js"></script>
<script src="js/permission/GroupManager.js"></script>

View file

@ -238,7 +238,7 @@ class IconManager {
return $("<div class='icon client-group_" + id + "'></div>");
let tag = $("<div></div>");
tag.addClass("icon_empty");
let img = $("<img/>");
let img = $.spawn("img");
img.attr("width", 16).attr("height", 16).attr("alt", "");
let icon = this.resolveCached(id);
if (icon) {

File diff suppressed because one or more lines are too long

View file

@ -311,7 +311,7 @@ class IconManager {
let tag = $("<div></div>");
tag.addClass("icon_empty");
let img = $("<img/>");
let img = $.spawn("img");
img.attr("width", 16).attr("height", 16).attr("alt", "");
let icon = this.resolveCached(id);

View file

@ -20,8 +20,6 @@ class InfoBar {
set currentSelected(entry) {
if (this._currentSelected == entry)
return;
if (!entry)
return;
this._currentSelected = entry;
this.buildBar();
}
@ -38,7 +36,9 @@ class InfoBar {
this._htmlTag.find(".online").text(formatDate(this._currentSelected.calculateOnlineTime()));
}
buildBar() {
this._htmlTag.html("");
this._htmlTag.empty();
if (!this._currentSelected)
return;
for (let timer of this.timers)
clearTimeout(timer);
for (let timer of this.intervals)

File diff suppressed because one or more lines are too long

View file

@ -31,7 +31,6 @@ class InfoBar {
set currentSelected(entry: ServerEntry | ChannelEntry | ClientEntry) {
if(this._currentSelected == entry) return;
if(!entry) return;
this._currentSelected = entry;
this.buildBar();
@ -55,7 +54,8 @@ class InfoBar {
}
private buildBar() {
this._htmlTag.html("");
this._htmlTag.empty();
if(!this._currentSelected) return;
for(let timer of this.timers)
clearTimeout(timer);

View file

@ -7,6 +7,25 @@
/// <reference path="permission/PermissionManager.ts" />
/// <reference path="permission/GroupManager.ts" />
/// <reference path="ui/ControlBar.ts" />
var DisconnectReason;
(function (DisconnectReason) {
DisconnectReason[DisconnectReason["CONNECT_FAILURE"] = 0] = "CONNECT_FAILURE";
DisconnectReason[DisconnectReason["CONNECTION_CLOSED"] = 1] = "CONNECTION_CLOSED";
DisconnectReason[DisconnectReason["CONNECTION_FATAL_ERROR"] = 2] = "CONNECTION_FATAL_ERROR";
DisconnectReason[DisconnectReason["CONNECTION_PING_TIMEOUT"] = 3] = "CONNECTION_PING_TIMEOUT";
DisconnectReason[DisconnectReason["CLIENT_KICKED"] = 4] = "CLIENT_KICKED";
DisconnectReason[DisconnectReason["CLIENT_BANNED"] = 5] = "CLIENT_BANNED";
DisconnectReason[DisconnectReason["SERVER_CLOSED"] = 6] = "SERVER_CLOSED";
DisconnectReason[DisconnectReason["UNKNOWN"] = 7] = "UNKNOWN";
})(DisconnectReason || (DisconnectReason = {}));
var ConnectionState;
(function (ConnectionState) {
ConnectionState[ConnectionState["UNCONNECTED"] = 0] = "UNCONNECTED";
ConnectionState[ConnectionState["CONNECTING"] = 1] = "CONNECTING";
ConnectionState[ConnectionState["INITIALISING"] = 2] = "INITIALISING";
ConnectionState[ConnectionState["CONNECTED"] = 3] = "CONNECTED";
ConnectionState[ConnectionState["DISCONNECTING"] = 4] = "DISCONNECTING";
})(ConnectionState || (ConnectionState = {}));
var ViewReasonId;
(function (ViewReasonId) {
ViewReasonId[ViewReasonId["VREASON_USER_ACTION"] = 0] = "VREASON_USER_ACTION";
@ -28,7 +47,7 @@ class TSClient {
this.settings = new Settings(this);
this.selectInfo = new InfoBar(this, $("#select_info"));
this.channelTree = new ChannelTree(this, $("#channelTree"));
this.serverConnection = new ServerConnection(this); //87.106.252.164
this.serverConnection = new ServerConnection(this);
this.fileManager = new FileManager(this);
this.permissions = new PermissionManager(this);
this.groups = new GroupManager(this);
@ -38,17 +57,8 @@ class TSClient {
this.channelTree.registerClient(this._ownEntry);
}
setup() {
const self = this;
this.serverConnection.on_connected = function () {
console.log("Client connected!");
self.settings.loadServer();
chat.serverChat().appendMessage("Connected");
self.serverConnection.sendCommand("channelsubscribeall");
self.permissions.requestPermissionList();
if (self.groups.serverGroups.length == 0)
self.groups.requestGroups();
};
this.controlBar.initialise();
this.serverConnection.on_connected = this.onConnected.bind(this);
}
startConnection(addr) {
let idx = addr.lastIndexOf(':');
@ -60,8 +70,10 @@ class TSClient {
}
else {
host = addr;
port = 19978;
port = 19974;
}
console.log("Start connection to " + host + ":" + port);
this.channelTree.initialiseHead(addr);
this.serverConnection.startConnection(host, port);
}
getClient() { return this._ownEntry; }
@ -70,14 +82,54 @@ class TSClient {
this._clientId = id;
this._ownEntry["_clientId"] = id;
}
get clientId() {
return this._clientId;
}
getServerConnection() { return this.serverConnection; }
/**
* LISTENER
*/
onConnected() {
console.log("Client connected!");
this.settings.loadServer();
chat.serverChat().appendMessage("Connected");
this.serverConnection.sendCommand("channelsubscribeall");
this.permissions.requestPermissionList();
if (this.groups.serverGroups.length == 0)
this.groups.requestGroups();
this.controlBar.updateProperties();
}
//Sould be triggered by `notifyclientleftview`
handleOwnDisconnect(json) {
handleDisconnect(type, data = {}) {
switch (type) {
case DisconnectReason.CONNECT_FAILURE:
console.error("Could not connect to remote host! Exception");
console.error(data);
createErrorModal("Could not connect", "Could not connect to remote host (Connection refused)").open();
break;
case DisconnectReason.CONNECTION_CLOSED:
console.error("Lost connection to remote server!");
createErrorModal("Connection closed", "The connection was closed by remote host").open();
break;
case DisconnectReason.CONNECTION_PING_TIMEOUT:
console.error("Connection ping timeout");
createErrorModal("Connection lost", "Lost connection to remote host (Ping timeout)<br>Even possible?").open();
break;
case DisconnectReason.SERVER_CLOSED:
chat.serverChat().appendError("Server closed ({})", data.reasonmsg);
createErrorModal("Server closed", "The server is closed.<br>" +
"Reason: " + data.reasonmsg).open();
break;
default:
console.error("Got uncaught disconnect!");
console.error("Type: " + type + " Data:");
console.error(data);
break;
}
this.selectInfo.currentSelected = null;
this.channelTree.reset();
this.voiceConnection.dropSession();
this.serverConnection.disconnect();
}
}
//# sourceMappingURL=client.js.map

View file

@ -1 +1 @@
{"version":3,"file":"client.js","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"client.js","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"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"}

View file

@ -8,6 +8,25 @@
/// <reference path="permission/GroupManager.ts" />
/// <reference path="ui/ControlBar.ts" />
enum DisconnectReason {
CONNECT_FAILURE,
CONNECTION_CLOSED,
CONNECTION_FATAL_ERROR,
CONNECTION_PING_TIMEOUT,
CLIENT_KICKED,
CLIENT_BANNED,
SERVER_CLOSED,
UNKNOWN
}
enum ConnectionState {
UNCONNECTED,
CONNECTING,
INITIALISING,
CONNECTED,
DISCONNECTING
}
enum ViewReasonId {
VREASON_USER_ACTION = 0,
VREASON_MOVED = 1,
@ -41,7 +60,7 @@ class TSClient {
this.settings = new Settings(this);
this.selectInfo = new InfoBar(this, $("#select_info"));
this.channelTree = new ChannelTree(this, $("#channelTree"));
this.serverConnection = new ServerConnection(this); //87.106.252.164
this.serverConnection = new ServerConnection(this);
this.fileManager = new FileManager(this);
this.permissions = new PermissionManager(this);
this.groups = new GroupManager(this);
@ -52,17 +71,9 @@ class TSClient {
}
setup() {
const self = this;
this.serverConnection.on_connected = function () {
console.log("Client connected!");
self.settings.loadServer();
chat.serverChat().appendMessage("Connected");
self.serverConnection.sendCommand("channelsubscribeall");
self.permissions.requestPermissionList();
if(self.groups.serverGroups.length == 0)
self.groups.requestGroups();
};
this.controlBar.initialise();
this.serverConnection.on_connected = this.onConnected.bind(this);
}
startConnection(addr: string) {
@ -75,8 +86,10 @@ class TSClient {
host = addr.substr(0, idx);
} else {
host = addr;
port = 19978;
port = 19974;
}
console.log("Start connection to " + host + ":" + port);
this.channelTree.initialiseHead(addr);
this.serverConnection.startConnection(host, port);
}
@ -89,6 +102,10 @@ class TSClient {
this._ownEntry["_clientId"] = id;
}
get clientId() {
return this._clientId;
}
getServerConnection() : ServerConnection { return this.serverConnection; }
@ -96,10 +113,60 @@ class TSClient {
* LISTENER
*/
onConnected() {
console.log("Client connected!");
this.settings.loadServer();
chat.serverChat().appendMessage("Connected");
this.serverConnection.sendCommand("channelsubscribeall");
this.permissions.requestPermissionList();
if(this.groups.serverGroups.length == 0)
this.groups.requestGroups();
this.controlBar.updateProperties();
}
//Sould be triggered by `notifyclientleftview`
handleOwnDisconnect(json) {
handleDisconnect(type: DisconnectReason, data: any = {}) {
switch (type) {
case DisconnectReason.CONNECT_FAILURE:
console.error("Could not connect to remote host! Exception");
console.error(data);
createErrorModal(
"Could not connect",
"Could not connect to remote host (Connection refused)"
).open();
break;
case DisconnectReason.CONNECTION_CLOSED:
console.error("Lost connection to remote server!");
createErrorModal(
"Connection closed",
"The connection was closed by remote host"
).open();
break;
case DisconnectReason.CONNECTION_PING_TIMEOUT:
console.error("Connection ping timeout");
createErrorModal(
"Connection lost",
"Lost connection to remote host (Ping timeout)<br>Even possible?"
).open();
break;
case DisconnectReason.SERVER_CLOSED:
chat.serverChat().appendError("Server closed ({})", data.reasonmsg);
createErrorModal(
"Server closed",
"The server is closed.<br>" +
"Reason: " + data.reasonmsg
).open();
break;
default:
console.error("Got uncaught disconnect!");
console.error("Type: " + type + " Data:");
console.error(data);
break;
}
this.selectInfo.currentSelected = null;
this.channelTree.reset();
this.voiceConnection.dropSession();
this.serverConnection.disconnect();
}
}

View file

@ -1,44 +1,58 @@
class SampleBuffer {
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
class BufferChunk {
constructor(buffer) {
this.buffer = buffer;
this.index = 0;
}
copyRangeTo(target, maxLength, offset) {
let copy = Math.min(this.buffer.length - this.index, maxLength);
for (let channel = 0; channel < this.buffer.numberOfChannels; channel++) {
target.getChannelData(channel).set(this.buffer.getChannelData(channel).subarray(this.index, this.index + copy), offset);
}
return copy;
}
}
class Codec {
constructor(codecSampleRate) {
this.on_encoded_data = ($) => { };
this._sampleBuffer = [];
this._chunks = [];
this.channelCount = 1;
this.samplesPerUnit = 960;
this._codecSampleRate = codecSampleRate;
this._decodeResampler = new Resampler();
this._encodeResampler = new Resampler(codecSampleRate);
this._decodeResampler = new AudioResampler();
this._encodeResampler = new AudioResampler(codecSampleRate);
}
bufferedSamples(max = 0) {
let value = 0;
for (let i = 0; i < this._sampleBuffer.length && value < max; i++)
value += this._sampleBuffer[i].buffer.length - this._sampleBuffer[i].index;
console.log(value + " / " + max);
for (let i = 0; i < this._chunks.length && value < max; i++)
value += this._chunks[i].buffer.length - this._chunks[i].index;
return value;
}
encodeSamples(pcm) {
this._encodeResampler.resample(pcm).then(buffer => this.encodeSamples0(buffer))
.catch(error => console.error("Could not resample PCM data for codec. Error:" + error));
return __awaiter(this, void 0, void 0, function* () {
this._encodeResampler.resample(pcm).then(buffer => this.encodeSamples0(buffer))
.catch(error => console.error("Could not resample PCM data for codec. Error:" + error));
});
}
encodeSamples0(buffer) {
console.log(buffer);
this._sampleBuffer.push(new SampleBuffer(buffer.getChannelData(0))); //TODO multi channel!
this._chunks.push(new BufferChunk(buffer)); //TODO multi channel!
while (this.bufferedSamples(this.samplesPerUnit) >= this.samplesPerUnit) {
let buffer = new Float32Array(this.samplesPerUnit);
let buffer = AudioController.globalContext.createBuffer(this.channelCount, this.samplesPerUnit, this._codecSampleRate);
let index = 0;
while (index < this.samplesPerUnit) {
let buf = this._sampleBuffer[0];
let len = Math.min(buf.buffer.length - buf.index, this.samplesPerUnit - index);
buffer.set(buf.buffer.subarray(buf.index, buf.index + len));
index += len;
buf.index += len;
console.log(buf.index + " - " + buf.buffer.length);
let buf = this._chunks[0];
let cpyBytes = buf.copyRangeTo(buffer, this.samplesPerUnit - index, index);
index += cpyBytes;
buf.index += cpyBytes;
if (buf.index == buf.buffer.length)
this._sampleBuffer.pop_front();
this._chunks.pop_front();
}
let result = this.encode(buffer);
if (result instanceof Uint8Array)
@ -52,60 +66,94 @@ class Codec {
return this.decode(data).then(buffer => this._decodeResampler.resample(buffer));
}
}
class OpusCodec extends Codec {
constructor() {
super(48000);
this.channelCount = 1;
class RawCodec extends Codec {
constructor(codecSampleRate) {
super(codecSampleRate);
this.bufferSize = 4096 * 4;
}
name() {
return "Opus";
return "raw";
}
initialise() {
this.fn_newHandle = Module.cwrap("codec_opus_createNativeHandle", "pointer", ["number"]);
this.fn_decode = Module.cwrap("codec_opus_decode", "number", ["pointer", "pointer", "number", "number"]); /* codec_opus_decode(handle, buffer, length, maxlength) */
this.fn_encode = Module.cwrap("codec_opus_encode", "number", ["pointer", "pointer", "number", "number"]);
this.nativeHandle = this.fn_newHandle(1);
this.converterRaw = Module._malloc(this.bufferSize);
this.converter = new Uint8Array(Module.HEAPU8.buffer, this.converterRaw, this.bufferSize);
}
deinitialise() { } //TODO
deinitialise() { }
decode(data) {
return new Promise((resolve, reject) => {
let maxBytes = 4096;
let buffer = Module._malloc(maxBytes);
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
heapBytes.set(data);
let result = this.fn_decode(this.nativeHandle, heapBytes.byteOffset, data.byteLength, maxBytes);
if (result < 0) {
Module._free(buffer);
reject("invalid result on decode (" + result + ")");
return;
}
let buf = Module.HEAPF32.slice(heapBytes.byteOffset / 4, (heapBytes.byteOffset / 4) + (result * this.channelCount));
Module._free(buffer);
let audioBuf = AudioController.globalContext.createBuffer(this.channelCount, result, this._codecSampleRate);
this.converter.set(data);
let buf = Module.HEAPF32.slice(this.converter.byteOffset / 4, (this.converter.byteOffset / 4) + data.length / 4);
let audioBuf = AudioController.globalContext.createBuffer(1, data.length / 4, this._codecSampleRate);
audioBuf.copyToChannel(buf, 0);
resolve(audioBuf);
});
}
encode(data) {
let maxBytes = data.byteLength;
let buffer = Module._malloc(maxBytes);
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
heapBytes.set(new Uint8Array(data.buffer));
let result = this.fn_encode(this.nativeHandle, heapBytes.byteOffset, data.length, maxBytes);
return new Uint8Array(data.getChannelData(0));
}
}
var OpusType;
(function (OpusType) {
OpusType[OpusType["VOIP"] = 2048] = "VOIP";
OpusType[OpusType["AUDIO"] = 2049] = "AUDIO";
OpusType[OpusType["RESTRICTED_LOWDELAY"] = 2051] = "RESTRICTED_LOWDELAY";
})(OpusType || (OpusType = {}));
class OpusCodec extends Codec {
constructor(channelCount, type) {
super(48000);
this.bufferSize = 4096 * 2;
super.channelCount = channelCount;
this.type = type;
}
name() {
return "Opus (Type: " + OpusCodec[this.type] + " Channels: " + this.channelCount + ")";
}
initialise() {
this.fn_newHandle = Module.cwrap("codec_opus_createNativeHandle", "pointer", ["number", "number"]);
this.fn_decode = Module.cwrap("codec_opus_decode", "number", ["pointer", "pointer", "number", "number"]); /* codec_opus_decode(handle, buffer, length, maxlength) */
this.fn_encode = Module.cwrap("codec_opus_encode", "number", ["pointer", "pointer", "number", "number"]);
this.nativeHandle = this.fn_newHandle(this.channelCount, this.type);
this.encodeBufferRaw = Module._malloc(this.bufferSize);
this.encodeBuffer = new Float32Array(Module.HEAPF32.buffer, this.encodeBufferRaw, this.bufferSize / 4);
this.decodeBufferRaw = Module._malloc(this.bufferSize);
this.decodeBuffer = new Uint8Array(Module.HEAPU8.buffer, this.decodeBufferRaw, this.bufferSize);
}
deinitialise() { } //TODO
decode(data) {
return new Promise((resolve, reject) => {
if (data.byteLength > this.decodeBuffer.byteLength)
throw "Data to long!";
this.decodeBuffer.set(data);
//console.log("decode(" + data.length + ")");
//console.log(data);
let result = this.fn_decode(this.nativeHandle, this.decodeBuffer.byteOffset, data.byteLength, this.decodeBuffer.byteLength);
if (result < 0) {
reject("invalid result on decode (" + result + ")");
return;
}
//console.log("decoded: " + result);
let buf = Module.HEAPF32.slice(this.decodeBuffer.byteOffset / 4, (this.decodeBuffer.byteOffset / 4) + (result * this.channelCount));
let audioBuf = AudioController.globalContext.createBuffer(this.channelCount, result, this._codecSampleRate);
for (let offset = 0; offset < result; offset++) {
for (let channel = 0; channel < this.channelCount; channel++)
audioBuf.getChannelData(channel)[offset] = buf[offset * this.channelCount + this.channelCount];
}
resolve(audioBuf);
});
}
encode(data) {
if (data.length * this.channelCount > this.encodeBuffer.length)
throw "Data to long!";
for (let offset = 0; offset < data.length; offset++) {
for (let channel = 0; channel < this.channelCount; channel++)
this.encodeBuffer[offset * this.channelCount + channel] = data.getChannelData(channel)[offset];
}
let result = this.fn_encode(this.nativeHandle, this.encodeBuffer.byteOffset, data.length, this.encodeBuffer.byteLength);
if (result < 0) {
Module._free(buffer);
return "invalid result on encode (" + result + ")";
}
let buf = Module.HEAP8.slice(heapBytes.byteOffset, heapBytes.byteOffset + result);
Module._free(buffer);
let buf = Module.HEAP8.slice(this.encodeBuffer.byteOffset, this.encodeBuffer.byteOffset + result);
return Uint8Array.from(buf);
}
_arrayToHeap(typedArray) {
let numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;
let ptr = Module._malloc(numBytes);
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
heapBytes.set(new Uint8Array(typedArray.buffer));
return heapBytes;
}
}
//# sourceMappingURL=Codec.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,27 +1,39 @@
class SampleBuffer {
buffer: Float32Array;
class BufferChunk {
buffer: AudioBuffer;
index: number;
constructor(buffer) {
constructor(buffer: AudioBuffer) {
this.buffer = buffer;
this.index = 0;
}
copyRangeTo(target: AudioBuffer, maxLength: number, offset: number) {
let copy = Math.min(this.buffer.length - this.index, maxLength);
for(let channel = 0; channel < this.buffer.numberOfChannels; channel++) {
target.getChannelData(channel).set(
this.buffer.getChannelData(channel).subarray(this.index, this.index + copy),
offset
);
}
return copy;
}
}
abstract class Codec {
on_encoded_data: (Uint8Array) => void = ($) => {};
protected _decodeResampler: Resampler;
protected _encodeResampler: Resampler;
protected _decodeResampler: AudioResampler;
protected _encodeResampler: AudioResampler;
protected _codecSampleRate: number;
protected _sampleBuffer: SampleBuffer[] = [];
protected _chunks: BufferChunk[] = [];
channelCount: number = 1;
samplesPerUnit: number = 960;
protected constructor(codecSampleRate: number){
this._codecSampleRate = codecSampleRate;
this._decodeResampler = new Resampler();
this._encodeResampler = new Resampler(codecSampleRate);
this._decodeResampler = new AudioResampler();
this._encodeResampler = new AudioResampler(codecSampleRate);
}
abstract name() : string;
@ -29,38 +41,35 @@ abstract class Codec {
abstract deinitialise();
protected abstract decode(data: Uint8Array) : Promise<AudioBuffer>;
protected abstract encode(data: Float32Array) : Uint8Array | string;
protected abstract encode(data: AudioBuffer) : Uint8Array | string;
protected bufferedSamples(max: number = 0) : number {
let value = 0;
for(let i = 0; i < this._sampleBuffer.length && value < max; i++)
value += this._sampleBuffer[i].buffer.length - this._sampleBuffer[i].index;
console.log(value + " / " + max);
for(let i = 0; i < this._chunks.length && value < max; i++)
value += this._chunks[i].buffer.length - this._chunks[i].index;
return value;
}
encodeSamples(pcm: AudioBuffer) {
async encodeSamples(pcm: AudioBuffer) {
this._encodeResampler.resample(pcm).then(buffer => this.encodeSamples0(buffer))
.catch(error => console.error("Could not resample PCM data for codec. Error:" + error));
}
private encodeSamples0(buffer: AudioBuffer) {
console.log(buffer);
this._sampleBuffer.push(new SampleBuffer(buffer.getChannelData(0))); //TODO multi channel!
this._chunks.push(new BufferChunk(buffer)); //TODO multi channel!
while(this.bufferedSamples(this.samplesPerUnit) >= this.samplesPerUnit) {
let buffer = new Float32Array(this.samplesPerUnit);
let buffer = AudioController.globalContext.createBuffer(this.channelCount, this.samplesPerUnit, this._codecSampleRate);
let index = 0;
while(index < this.samplesPerUnit) {
let buf = this._sampleBuffer[0];
let len = Math.min(buf.buffer.length - buf.index, this.samplesPerUnit - index);
buffer.set(buf.buffer.subarray(buf.index, buf.index + len));
index += len;
buf.index += len;
console.log(buf.index + " - " + buf.buffer.length);
let buf = this._chunks[0];
let cpyBytes = buf.copyRangeTo(buffer, this.samplesPerUnit - index, index);
index += cpyBytes;
buf.index += cpyBytes;
if(buf.index == buf.buffer.length)
this._sampleBuffer.pop_front();
this._chunks.pop_front();
}
let result = this.encode(buffer);
@ -75,73 +84,124 @@ abstract class Codec {
}
}
class RawCodec extends Codec {
converterRaw: any;
converter: Uint8Array;
bufferSize: number = 4096 * 4;
constructor(codecSampleRate: number){
super(codecSampleRate);
}
name(): string {
return "raw";
}
initialise() {
this.converterRaw = Module._malloc(this.bufferSize);
this.converter = new Uint8Array(Module.HEAPU8.buffer, this.converterRaw, this.bufferSize);
}
deinitialise() { }
protected decode(data: Uint8Array): Promise<AudioBuffer> {
return new Promise<AudioBuffer>((resolve, reject) => {
this.converter.set(data);
let buf = Module.HEAPF32.slice(this.converter.byteOffset / 4, (this.converter.byteOffset / 4) + data.length / 4);
let audioBuf = AudioController.globalContext.createBuffer(1, data.length / 4, this._codecSampleRate);
audioBuf.copyToChannel(buf, 0);
resolve(audioBuf);
});
}
protected encode(data: AudioBuffer): Uint8Array | string {
return new Uint8Array(data.getChannelData(0));
}
}
enum OpusType {
VOIP = 2048,
AUDIO = 2049,
RESTRICTED_LOWDELAY = 2051
}
class OpusCodec extends Codec {
private nativeHandle: any;
private channelCount: number = 1;
private type: OpusType;
private fn_newHandle: any;
private fn_decode: any;
private fn_encode: any;
constructor() {
private bufferSize = 4096 * 2;
private encodeBufferRaw: any;
private encodeBuffer: Float32Array;
private decodeBufferRaw: any;
private decodeBuffer: Uint8Array;
constructor(channelCount: number, type: OpusType) {
super(48000);
super.channelCount = channelCount;
this.type = type;
}
name(): string {
return "Opus";
return "Opus (Type: " + OpusCodec[this.type] + " Channels: " + this.channelCount + ")";
}
initialise() {
this.fn_newHandle = Module.cwrap("codec_opus_createNativeHandle", "pointer", ["number"]);
this.fn_newHandle = Module.cwrap("codec_opus_createNativeHandle", "pointer", ["number", "number"]);
this.fn_decode = Module.cwrap("codec_opus_decode", "number", ["pointer", "pointer", "number", "number"]); /* codec_opus_decode(handle, buffer, length, maxlength) */
this.fn_encode = Module.cwrap("codec_opus_encode", "number", ["pointer", "pointer", "number", "number"]);
this.nativeHandle = this.fn_newHandle(1);
this.nativeHandle = this.fn_newHandle(this.channelCount, this.type);
this.encodeBufferRaw = Module._malloc(this.bufferSize);
this.encodeBuffer = new Float32Array(Module.HEAPF32.buffer, this.encodeBufferRaw, this.bufferSize / 4);
this.decodeBufferRaw = Module._malloc(this.bufferSize);
this.decodeBuffer = new Uint8Array(Module.HEAPU8.buffer, this.decodeBufferRaw, this.bufferSize);
}
deinitialise() { } //TODO
decode(data: Uint8Array): Promise<AudioBuffer> {
return new Promise<AudioBuffer>((resolve, reject) => {
let maxBytes = 4096;
let buffer = Module._malloc(maxBytes);
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
heapBytes.set(data);
let result = this.fn_decode(this.nativeHandle, heapBytes.byteOffset, data.byteLength, maxBytes);
if(data.byteLength > this.decodeBuffer.byteLength) throw "Data to long!";
this.decodeBuffer.set(data);
//console.log("decode(" + data.length + ")");
//console.log(data);
let result = this.fn_decode(this.nativeHandle, this.decodeBuffer.byteOffset, data.byteLength, this.decodeBuffer.byteLength);
if(result < 0) {
Module._free(buffer);
reject("invalid result on decode (" + result + ")");
return;
}
let buf = Module.HEAPF32.slice(heapBytes.byteOffset / 4, (heapBytes.byteOffset / 4) + (result * this.channelCount));
Module._free(buffer);
//console.log("decoded: " + result);
let buf = Module.HEAPF32.slice(this.decodeBuffer.byteOffset / 4, (this.decodeBuffer.byteOffset / 4) + (result * this.channelCount));
let audioBuf = AudioController.globalContext.createBuffer(this.channelCount, result, this._codecSampleRate);
audioBuf.copyToChannel(buf, 0);
for(let offset = 0; offset < result; offset++) {
for(let channel = 0; channel < this.channelCount; channel++)
audioBuf.getChannelData(channel)[offset] = buf[offset * this.channelCount + this.channelCount];
}
resolve(audioBuf);
});
}
encode(data: Float32Array): Uint8Array | string {
let maxBytes = data.byteLength;
let buffer = Module._malloc(maxBytes);
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
heapBytes.set(new Uint8Array(data.buffer));
let result = this.fn_encode(this.nativeHandle, heapBytes.byteOffset, data.length, maxBytes);
encode(data: AudioBuffer): Uint8Array | string {
if(data.length * this.channelCount > this.encodeBuffer.length) throw "Data to long!";
for(let offset = 0; offset < data.length; offset++) {
for(let channel = 0; channel < this.channelCount; channel++)
this.encodeBuffer[offset * this.channelCount + channel] = data.getChannelData(channel)[offset];
}
let result = this.fn_encode(this.nativeHandle, this.encodeBuffer.byteOffset, data.length, this.encodeBuffer.byteLength);
if(result < 0) {
Module._free(buffer);
return "invalid result on encode (" + result + ")";
}
let buf = Module.HEAP8.slice(heapBytes.byteOffset, heapBytes.byteOffset + result);
Module._free(buffer);
let buf = Module.HEAP8.slice(this.encodeBuffer.byteOffset , this.encodeBuffer.byteOffset + result);
return Uint8Array.from(buf);
}
private _arrayToHeap(typedArray: any){
let numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;
let ptr = Module._malloc(numBytes);
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
heapBytes.set(new Uint8Array(typedArray.buffer));
return heapBytes;
}
}

View file

@ -15,15 +15,13 @@ class ReturnListener {
}
class ServerConnection {
constructor(client) {
this._connectionState = ConnectionState.UNCONNECTED;
this._connectTimeoutHandler = undefined;
this.on_connect = () => {
console.log("Client connected!");
chat.serverChat().appendMessage("Client connected");
};
this.on_connected = () => { };
this.on_disconnect = (reason) => {
console.error("Client disconnected!");
chat.serverChat().appendError("Client disconnected. Reason " + reason);
};
this._client = client;
this._socket = null;
this.commandHandler = new ConnectionCommandHandler(this);
@ -33,38 +31,66 @@ class ServerConnection {
generateReturnCode() {
return (this._retCodeIdx++).toString();
}
startConnection(host, port) {
startConnection(host, port, timeout = 1000) {
if (this._connectTimeoutHandler) {
clearTimeout(this._connectTimeoutHandler);
this._connectTimeoutHandler = null;
this.disconnect();
}
this.updateConnectionState(ConnectionState.CONNECTING);
this._remoteHost = host;
this._remotePort = port;
const self = this;
try {
this._connectTimeoutHandler = setTimeout(() => {
this.disconnect();
this._client.handleDisconnect(DisconnectReason.CONNECT_FAILURE);
}, timeout);
this._socket = new WebSocket('ws:' + this._remoteHost + ":" + this._remotePort);
clearTimeout(this._connectTimeoutHandler);
this._connectTimeoutHandler = null;
this._socket.onopen = function () {
self.on_connect();
};
this._socket.onclose = function () {
self.on_disconnect("remote closed");
this._socket.onclose = event => {
this._client.handleDisconnect(DisconnectReason.CONNECTION_CLOSED, {
code: event.code,
reason: event.reason,
event: event
});
};
this._socket.onerror = function (e) {
console.log("Got error: (" + self._socket.readyState + ")");
console.log(e);
};
this._socket.onmessage = function (msg) {
self.onMessage(msg.data);
self.handleWebSocketMessage(msg.data);
};
this.updateConnectionState(ConnectionState.INITIALISING);
}
catch (e) {
console.log("Got exception:");
console.log(e);
this.disconnect();
this._client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, e);
}
}
disconnect() {
this._socket.close();
this._socket = null;
updateConnectionState(state) {
this._connectionState = state;
}
onMessage(data) {
disconnect() {
if (this._connectionState == ConnectionState.UNCONNECTED)
return;
if (this._socket)
this._socket.close();
this._socket = null;
this.updateConnectionState(ConnectionState.UNCONNECTED);
for (let future of this._retListener)
future.reject("Connection closed");
this._retListener = [];
this._retCodeIdx = 0;
}
handleWebSocketMessage(data) {
if (typeof (data) === "string") {
var json;
let json;
try {
json = JSON.parse(data);
}
@ -95,8 +121,8 @@ class ServerConnection {
}
fn.call(this.commandHandler, json["data"]);
}
send(json) {
this._socket.send(json);
sendData(data) {
this._socket.send(data);
}
sendCommand(command, data = {}, logResult = true) {
const _this = this;
@ -162,7 +188,7 @@ class ServerConnection {
return this.sendCommand("sendtextmessage", { "targetmode": 1, "target": target.clientId(), "msg": message });
}
updateClient(key, value) {
var data = {};
let data = {};
data[key] = value;
return this.sendCommand("clientupdate", data);
}
@ -207,9 +233,7 @@ class ConnectionCommandHandler {
}
handleCommandServerInit(json) {
//We could setup the voice channel
console.log(this.connection);
console.log(this.connection._client);
console.log(this.connection._client.voiceConnection);
console.log("Setting up voice ");
this.connection._client.voiceConnection.createSession();
json = json[0]; //Only one bulk
this.connection._client.clientId = json["aclid"];
@ -337,8 +361,12 @@ class ConnectionCommandHandler {
return 0;
}
if (client == this.connection._client.getClient()) {
this.connection.on_disconnect(json["reasonmsg"]);
this.connection.disconnect();
if (json["reasonid"] == ViewReasonId.VREASON_BAN)
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_BANNED, json);
else if (json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK)
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_KICKED, json);
else
this.connection._client.handleDisconnect(DisconnectReason.UNKNOWN, json);
return;
}
let channel_from = tree.findChannel(json["cfid"]);

File diff suppressed because one or more lines are too long

View file

@ -34,8 +34,11 @@ class ServerConnection {
_remoteHost: string;
_remotePort: number;
_socket: WebSocket;
_connectionState: ConnectionState = ConnectionState.UNCONNECTED;
commandHandler: ConnectionCommandHandler;
private _connectTimeoutHandler: NodeJS.Timer = undefined;
private _retCodeIdx: number;
private _retListener: ReturnListener<CommandResult>[];
@ -54,28 +57,40 @@ class ServerConnection {
};
on_connected: () => void = () => {};
on_disconnect: (reason: string | any) => void = (reason: string | any) => {
console.error("Client disconnected!");
chat.serverChat().appendError("Client disconnected. Reason " + reason);
};
private generateReturnCode() : string {
return (this._retCodeIdx++).toString();
}
startConnection(host : string, port : number) {
startConnection(host : string, port : number, timeout: number = 1000) {
if(this._connectTimeoutHandler) {
clearTimeout(this._connectTimeoutHandler);
this._connectTimeoutHandler = null;
this.disconnect();
}
this.updateConnectionState(ConnectionState.CONNECTING);
this._remoteHost = host;
this._remotePort = port;
const self = this;
try {
this._connectTimeoutHandler = setTimeout(() => {
this.disconnect();
this._client.handleDisconnect(DisconnectReason.CONNECT_FAILURE);
}, timeout);
this._socket = new WebSocket('ws:' + this._remoteHost + ":" + this._remotePort);
clearTimeout(this._connectTimeoutHandler);
this._connectTimeoutHandler = null;
this._socket.onopen = function () {
self.on_connect();
};
this._socket.onclose = function () {
self.on_disconnect("remote closed");
this._socket.onclose = event => {
this._client.handleDisconnect(DisconnectReason.CONNECTION_CLOSED, {
code: event.code,
reason: event.reason,
event: event
});
};
this._socket.onerror = function (e) {
@ -84,22 +99,34 @@ class ServerConnection {
};
this._socket.onmessage = function (msg) {
self.onMessage(msg.data);
self.handleWebSocketMessage(msg.data);
};
this.updateConnectionState(ConnectionState.INITIALISING);
} catch (e) {
console.log("Got exception:");
console.log(e);
this.disconnect();
this._client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, e);
}
}
disconnect() {
this._socket.close();
this._socket = null;
updateConnectionState(state: ConnectionState) {
this._connectionState = state;
}
private onMessage(data) {
disconnect() {
if(this._connectionState == ConnectionState.UNCONNECTED) return;
if(this._socket) this._socket.close();
this._socket = null;
this.updateConnectionState(ConnectionState.UNCONNECTED);
for(let future of this._retListener)
future.reject("Connection closed");
this._retListener = [];
this._retCodeIdx = 0;
}
private handleWebSocketMessage(data) {
if(typeof(data) === "string") {
var json;
let json;
try {
json = JSON.parse(data);
} catch(e) {
@ -130,8 +157,8 @@ class ServerConnection {
fn.call(this.commandHandler, json["data"]);
}
send(json) {
this._socket.send(json);
sendData(data: any) { //TODO check stuff?
this._socket.send(data);
}
sendCommand(command: string, data: any = {}, logResult: boolean = true) : Promise<CommandResult> {
@ -184,7 +211,6 @@ class ServerConnection {
/**
* HELPER METHODS
*/
joinChannel(channel: ChannelEntry, password: string = "") : Promise<CommandResult> {
return this.sendCommand("clientmove", [{
"clid": this._client.getClientId(),
@ -203,14 +229,14 @@ class ServerConnection {
}
updateClient(key: string, value: string) : Promise<CommandResult> {
var data = {};
let data = {};
data[key] = value;
return this.sendCommand("clientupdate", data);
}
}
class ConnectionCommandHandler {
connection: ServerConnection;
readonly connection: ServerConnection;
constructor(connection) {
this.connection = connection;
@ -257,9 +283,7 @@ class ConnectionCommandHandler {
handleCommandServerInit(json){
//We could setup the voice channel
console.log(this.connection);
console.log(this.connection._client);
console.log(this.connection._client.voiceConnection);
console.log("Setting up voice ");
this.connection._client.voiceConnection.createSession();
@ -394,8 +418,12 @@ class ConnectionCommandHandler {
return 0;
}
if(client == this.connection._client.getClient()) {
this.connection.on_disconnect(json["reasonmsg"]);
this.connection.disconnect();
if(json["reasonid"] == ViewReasonId.VREASON_BAN)
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_BANNED, json);
else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK)
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_KICKED, json);
else
this.connection._client.handleDisconnect(DisconnectReason.UNKNOWN, json);
return;
}

View file

@ -8,9 +8,10 @@ $(document).bind("mousedown", function (e) {
});
let contextMenuCloseFn = undefined;
function despawnContextMenu() {
if (!$(".contextMenu").is(":visible"))
let menue = $(".contextMenu");
if (!menue.is(":visible"))
return;
$(".contextMenu").hide(100);
menue.hide(100);
if (contextMenuCloseFn)
contextMenuCloseFn();
}

View file

@ -1 +1 @@
{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["contextMenu.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["contextMenu.ts"],"names":[],"mappings":"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"}

View file

@ -9,8 +9,9 @@ $(document).bind("mousedown", function (e) {
let contextMenuCloseFn = undefined;
function despawnContextMenu() {
if(!$(".contextMenu").is(":visible")) return;
$(".contextMenu").hide(100);
let menue = $(".contextMenu");
if(!menue.is(":visible")) return;
menue.hide(100);
if(contextMenuCloseFn) contextMenuCloseFn();
}

View file

@ -1,17 +1,19 @@
/// <reference path="chat.ts" />
/// <reference path="client.ts" />
/// <reference path="utils/modal.ts" />
var ccall = Module.ccall;
/// <reference path="ui/modal/ModalConnect.ts" />
let globalClient = new TSClient();
let chat = new ChatBox($("#chat"));
globalClient.setup();
globalClient.startConnection("localhost:19978"); //TODO remove only for testing
//globalClient.startConnection("localhost:19974"); //TODO remove only for testing
let modal = 0;
$("#test").click(function () {
console.log("Executing test function");
});
//$("#test").trigger("click");
$("#test_tab").tabify();
//Modals.spawnConnectModal();
Modals.spawnSettingsModal();
/*
createErrorModal("Could not connect to remote host",() => {
let tag = $.spawn("div");
@ -21,121 +23,5 @@ createErrorModal("Could not connect to remote host",() => {
}, {
footer: ""
}).open();
*/
let connectModal = createModal({
header: function () {
let header = $.spawn("div");
header.text("Create a new connection");
return header;
},
body: function () {
let tag = $("#tmpl_connect").contents();
let updateFields = function () {
let button = tag.parents(".modal-content").find(".connect_connect_button");
let field_address = tag.find(".connect_address");
let address = field_address.val().toString();
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.DOMAIN);
let field_nickname = tag.find(".connect_nickname");
let nickname = field_nickname.val().toString();
let flag_nickname = nickname.length >= 3 && nickname.length <= 32;
if (flag_address) {
if (field_address.hasClass("invalid_input"))
field_address.removeClass("invalid_input");
}
else {
if (!field_address.hasClass("invalid_input"))
field_address.addClass("invalid_input");
}
if (flag_nickname) {
if (field_nickname.hasClass("invalid_input"))
field_nickname.removeClass("invalid_input");
}
else {
if (!field_nickname.hasClass("invalid_input"))
field_nickname.addClass("invalid_input");
}
if (!flag_nickname || !flag_address) {
button.attr("disabled", "true");
}
else {
button.removeAttr("disabled");
}
};
tag.find(".connect_address").on("keyup", () => updateFields());
tag.find(".connect_nickname").on("keyup", () => updateFields());
//connect_address
return $("#tmpl_connect").contents();
},
footer: function () {
let tag = $.spawn("div");
tag.css("text-align", "right");
tag.css("margin-top", "3px");
tag.css("margin-bottom", "6px");
tag.addClass("modal-button-group");
let button = $.spawn("button");
button.addClass("connect_connect_button");
button.text("Connect");
button.on("click", function () {
connectModal.close();
let field_address = tag.parents(".modal-content").find(".connect_address");
let address = field_address.val().toString();
globalClient.startConnection(address);
});
tag.append(button);
return tag;
},
width: 600,
closeable: false
});
//connectModal.open();
var Regex = {
//DOMAIN<:port>
DOMAIN: /^(localhost|((([a-zA-Z0-9_-]{0,63}\.){0,253})?[a-zA-Z0-9_-]{0,63}\.[a-zA-Z]{2,5}))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
//IP<:port>
IP_V4: /(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
IP_V6: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/,
IP: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
};
/*
let channelCreate = createModal({
header: "Create channel",
body: () => {
let template = $("#tmpl_channel_edit").tmpl();
template = $.spawn("div").append(template);
let tag = template.tabify();
return tag;
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
let buttonCancel = $.spawn("button");
buttonCancel.text("Cancel");
let buttonOk = $.spawn("button");
buttonOk.text("Ok");
footer.append(buttonCancel);
footer.append(buttonOk);
return footer;
},
width: 500
}).open();
*/
/*
let createOpusCodec = Module.cwrap("createOpusCodec", "pointer", []);
let codec = createOpusCodec();
console.log("Codec: " + codec);
let printCodecName = Module.cwrap("printCodecName", "void", ["pointer"]);
console.log("Result: " + printCodecName(codec));
*/
/*
let opus = new OpusCodec();
opus.initialise();
opus.decode(new Uint8Array([0, 0, 9]));
opus.encode(new Float32Array([123, 22, 434, 55332]));
*/
//# sourceMappingURL=main.js.map

View file

@ -1 +1 @@
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,kCAAkC;AAClC,uCAAuC;AACvC,iDAAiD;AAGjD,IAAI,YAAY,GAAG,IAAI,QAAQ,EAAE,CAAC;AAClC,IAAI,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AACnC,YAAY,CAAC,KAAK,EAAE,CAAC;AACrB,iFAAiF;AAEjF,IAAI,KAAK,GAAG,CAAC,CAAC;AACd,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC;IACb,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AACH,8BAA8B;AAC9B,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC;AAExB,6BAA6B;AAC7B,MAAM,CAAC,kBAAkB,EAAE,CAAC;AAC5B;;;;;;;;;EASE"}

View file

@ -1,14 +1,13 @@
/// <reference path="chat.ts" />
/// <reference path="client.ts" />
/// <reference path="utils/modal.ts" />
/// <reference path="ui/modal/ModalConnect.ts" />
import ccall = Module.ccall;
let globalClient = new TSClient();
let chat = new ChatBox($("#chat"));
globalClient.setup();
globalClient.startConnection("localhost:19978"); //TODO remove only for testing
//globalClient.startConnection("localhost:19974"); //TODO remove only for testing
let modal = 0;
$("#test").click(function () {
@ -17,6 +16,8 @@ $("#test").click(function () {
//$("#test").trigger("click");
$("#test_tab").tabify();
//Modals.spawnConnectModal();
Modals.spawnSettingsModal();
/*
createErrorModal("Could not connect to remote host",() => {
let tag = $.spawn("div");
@ -26,132 +27,4 @@ createErrorModal("Could not connect to remote host",() => {
}, {
footer: ""
}).open();
*/
let connectModal = createModal({
header: function() {
let header = $.spawn("div");
header.text("Create a new connection");
return header;
},
body: function () {
let tag = $("#tmpl_connect").contents();
let updateFields = function () {
let button = tag.parents(".modal-content").find(".connect_connect_button");
let field_address = tag.find(".connect_address");
let address = field_address.val().toString();
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.DOMAIN);
let field_nickname = tag.find(".connect_nickname");
let nickname = field_nickname.val().toString();
let flag_nickname = nickname.length >= 3 && nickname.length <= 32;
if(flag_address) {
if(field_address.hasClass("invalid_input"))
field_address.removeClass("invalid_input");
} else {
if(!field_address.hasClass("invalid_input"))
field_address.addClass("invalid_input");
}
if(flag_nickname) {
if(field_nickname.hasClass("invalid_input"))
field_nickname.removeClass("invalid_input");
} else {
if(!field_nickname.hasClass("invalid_input"))
field_nickname.addClass("invalid_input");
}
if(!flag_nickname || !flag_address) {
button.attr("disabled", "true");
} else {
button.removeAttr("disabled");
}
}
tag.find(".connect_address").on("keyup", () => updateFields());
tag.find(".connect_nickname").on("keyup", () => updateFields());
//connect_address
return $("#tmpl_connect").contents();
},
footer: function () {
let tag = $.spawn("div");
tag.css("text-align", "right");
tag.css("margin-top", "3px");
tag.css("margin-bottom", "6px");
tag.addClass("modal-button-group");
let button = $.spawn("button");
button.addClass("connect_connect_button");
button.text("Connect");
button.on("click", function () {
connectModal.close();
let field_address = tag.parents(".modal-content").find(".connect_address");
let address = field_address.val().toString();
globalClient.startConnection(address);
});
tag.append(button);
return tag;
},
width: 600,
closeable: false
});
//connectModal.open();
var Regex = {
//DOMAIN<:port>
DOMAIN: /^(localhost|((([a-zA-Z0-9_-]{0,63}\.){0,253})?[a-zA-Z0-9_-]{0,63}\.[a-zA-Z]{2,5}))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
//IP<:port>
IP_V4: /(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
IP_V6: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/,
IP: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
}
/*
let channelCreate = createModal({
header: "Create channel",
body: () => {
let template = $("#tmpl_channel_edit").tmpl();
template = $.spawn("div").append(template);
let tag = template.tabify();
return tag;
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
let buttonCancel = $.spawn("button");
buttonCancel.text("Cancel");
let buttonOk = $.spawn("button");
buttonOk.text("Ok");
footer.append(buttonCancel);
footer.append(buttonOk);
return footer;
},
width: 500
}).open();
*/
/*
let createOpusCodec = Module.cwrap("createOpusCodec", "pointer", []);
let codec = createOpusCodec();
console.log("Codec: " + codec);
let printCodecName = Module.cwrap("printCodecName", "void", ["pointer"]);
console.log("Result: " + printCodecName(codec));
*/
/*
let opus = new OpusCodec();
opus.initialise();
opus.decode(new Uint8Array([0, 0, 9]));
opus.encode(new Float32Array([123, 22, 434, 55332]));
*/

View file

@ -14,25 +14,35 @@ class Settings {
_this.save();
}, 5 * 1000);
}
global(key) {
return this.cacheGlobal[key];
global(key, _default) {
let result = this.cacheGlobal[key];
return result ? result : _default;
}
server(key) {
return this.cacheServer[key];
}
changeGlobal(key, value) {
if (this.cacheGlobal[key] == value)
return;
this.updated = true;
this.cacheGlobal[key] = value;
if (Settings.UPDATE_DIRECT)
this.save();
}
changeServer(key, value) {
if (this.cacheServer[key] == value)
return;
this.updated = true;
this.cacheServer[key] = value;
if (Settings.UPDATE_DIRECT)
this.save();
}
loadServer() {
if (this.handle.channelTree.server) {
this.cacheServer = {};
console.warn("[Settings] tried to load settings for unknown server");
return;
}
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
if (!this.cacheServer)
@ -40,11 +50,13 @@ class Settings {
}
save() {
this.updated = false;
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
if (this.handle.channelTree.server) {
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
let server = JSON.stringify(this.cacheServer);
localStorage.setItem("settings.server_" + serverId, server);
}
let global = JSON.stringify(this.cacheGlobal);
let server = JSON.stringify(this.cacheServer);
localStorage.setItem("settings.global", global);
localStorage.setItem("settings.server_" + serverId, server);
}
}
Settings.UPDATE_DIRECT = true;

View file

@ -1 +1 @@
{"version":3,"file":"settings.js","sourceRoot":"","sources":["settings.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC;IASI,YAAY,MAAgB;QALpB,gBAAW,GAAG,EAAE,CAAC;QACjB,gBAAW,GAAG,EAAE,CAAC;QAEjB,YAAO,GAAY,KAAK,CAAC;QAG7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACvE,EAAE,CAAA,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;YAAC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YAC/B,EAAE,CAAA,CAAC,KAAK,CAAC,OAAO,CAAC;gBACb,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,CAAE,GAAW;QACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,CAAE,GAAW;QACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,KAAc;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAE9B,EAAE,CAAA,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtB,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,KAAc;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAE9B,EAAE,CAAA,CAAC,QAAQ,CAAC,aAAa,CAAC;YACtB,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,UAAU;QACN,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,+BAA+B,CAAC;QACzF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,kBAAkB,GAAG,QAAQ,CAAC,CAAC,CAAC;QACnF,EAAE,CAAA,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI;QACA,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,+BAA+B,CAAC;QACzF,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE9C,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAChD,YAAY,CAAC,OAAO,CAAC,kBAAkB,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC;IAChE,CAAC;;AAzDuB,sBAAa,GAAY,IAAI,CAAC"}
{"version":3,"file":"settings.js","sourceRoot":"","sources":["settings.ts"],"names":[],"mappings":"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"}

View file

@ -21,8 +21,9 @@ class Settings {
}, 5 * 1000);
}
global?(key: string) : string {
return this.cacheGlobal[key];
global?(key: string, _default?: string) : string {
let result = this.cacheGlobal[key];
return result ? result : _default;
}
server?(key: string) : string {
@ -30,6 +31,8 @@ class Settings {
}
changeGlobal(key: string, value?: string){
if(this.cacheGlobal[key] == value) return;
this.updated = true;
this.cacheGlobal[key] = value;
@ -38,6 +41,8 @@ class Settings {
}
changeServer(key: string, value?: string) {
if(this.cacheServer[key] == value) return;
this.updated = true;
this.cacheServer[key] = value;
@ -46,6 +51,11 @@ class Settings {
}
loadServer() {
if(this.handle.channelTree.server) {
this.cacheServer = {};
console.warn("[Settings] tried to load settings for unknown server");
return;
}
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
if(!this.cacheServer)
@ -54,11 +64,14 @@ class Settings {
save() {
this.updated = false;
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
let global = JSON.stringify(this.cacheGlobal);
let server = JSON.stringify(this.cacheServer);
if(this.handle.channelTree.server) {
let serverId = this.handle.channelTree.server.properties.virtualserver_unique_identifier;
let server = JSON.stringify(this.cacheServer);
localStorage.setItem("settings.server_" + serverId, server);
}
let global = JSON.stringify(this.cacheGlobal);
localStorage.setItem("settings.global", global);
localStorage.setItem("settings.server_" + serverId, server);
}
}

View file

@ -1,4 +1,5 @@
/// <reference path="../client.ts" />
/// <reference path="modal/ModalSettings.ts" />
/*
client_output_hardware Value: '1'
client_output_muted Value: '0'
@ -16,9 +17,11 @@ class ControlBar {
this.htmlTag = htmlTag;
}
initialise() {
this.htmlTag.find(".btn_connect").click(this.onConnect.bind(this));
this.htmlTag.find(".btn_client_away").click(this.onAway.bind(this));
this.htmlTag.find(".btn_mute_input").click(this.onInputMute.bind(this));
this.htmlTag.find(".btn_mute_output").click(this.onOutputMute.bind(this));
this.htmlTag.find(".btn_open_settings").click(this.onOpenSettings.bind(this));
//Need an initialise
this.muteInput = this.handle.settings.global("mute_input") == "1";
this.muteOutput = this.handle.settings.global("mute_output") == "1";
@ -107,5 +110,20 @@ class ControlBar {
let enabled = !this._muteInput && !this._muteOutput && !this._away;
this.handle.voiceConnection.voiceRecorder.update(enabled);
}
updateProperties() {
if (this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_input_muted: this._muteInput ? 1 : 0,
client_output_muted: this._muteOutput ? 1 : 0,
client_away: this._away ? 1 : 0,
client_away_message: this._awayMessage,
});
}
onOpenSettings() {
Modals.spawnSettingsModal();
}
onConnect() {
Modals.spawnConnectModal("localhost");
}
}
//# sourceMappingURL=ControlBar.js.map

View file

@ -1 +1 @@
{"version":3,"file":"ControlBar.js","sourceRoot":"","sources":["ControlBar.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"ControlBar.js","sourceRoot":"","sources":["ControlBar.ts"],"names":[],"mappings":"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"}

View file

@ -1,5 +1,5 @@
/// <reference path="../client.ts" />
/// <reference path="modal/ModalSettings.ts" />
/*
client_output_hardware Value: '1'
client_output_muted Value: '0'
@ -26,9 +26,12 @@ class ControlBar {
}
initialise() {
this.htmlTag.find(".btn_connect").click(this.onConnect.bind(this));
this.htmlTag.find(".btn_client_away").click(this.onAway.bind(this));
this.htmlTag.find(".btn_mute_input").click(this.onInputMute.bind(this));
this.htmlTag.find(".btn_mute_output").click(this.onOutputMute.bind(this));
this.htmlTag.find(".btn_open_settings").click(this.onOpenSettings.bind(this));
//Need an initialise
this.muteInput = this.handle.settings.global("mute_input") == "1";
@ -126,4 +129,22 @@ class ControlBar {
let enabled = !this._muteInput && !this._muteOutput && !this._away;
this.handle.voiceConnection.voiceRecorder.update(enabled);
}
updateProperties() {
if(this.handle.serverConnection.connected)
this.handle.serverConnection.sendCommand("clientupdate", {
client_input_muted: this._muteInput ? 1 : 0,
client_output_muted: this._muteOutput ? 1 : 0,
client_away: this._away ? 1 : 0,
client_away_message: this._awayMessage,
});
}
private onOpenSettings() {
Modals.spawnSettingsModal();
}
private onConnect() {
Modals.spawnConnectModal("localhost");
}
}

View file

@ -86,7 +86,7 @@ class ChannelEntry {
get htmlTag() {
if (this._htmlTag)
return this._htmlTag;
let tag = $("<div></div>");
let tag = $.spawn("div");
tag.attr("id", "channel_" + this.getChannelId());
tag.addClass("channel");
tag.append("<div class=\"icon_empty\"></div>");
@ -279,7 +279,8 @@ class ChannelEntry {
}
}
createChatTag(braces = false) {
var tag = $("<div></div>");
let tag = $.spawn("div");
tag.css("display", "table");
tag.css("cursor", "pointer");
tag.css("font-weight", "bold");
tag.css("color", "darkblue");

File diff suppressed because one or more lines are too long

View file

@ -103,7 +103,7 @@ class ChannelEntry {
get htmlTag() : JQuery<HTMLElement> {
if(this._htmlTag) return this._htmlTag;
let tag = $("<div></div>");
let tag = $.spawn("div");
tag.attr("id", "channel_" + this.getChannelId());
tag.addClass("channel");
@ -314,8 +314,9 @@ class ChannelEntry {
}
createChatTag(braces: boolean = false) : string {
var tag = $("<div></div>");
let tag = $.spawn("div");
tag.css("display", "table");
tag.css("cursor", "pointer");
tag.css("font-weight", "bold");
tag.css("color", "darkblue");

View file

@ -139,6 +139,7 @@ class ClientEntry {
tag.css("cursor", "pointer");
tag.css("font-weight", "bold");
tag.css("color", "darkblue");
tag.css("display", "table");
if (braces)
tag.text("\"" + name + "\"");
else

File diff suppressed because one or more lines are too long

View file

@ -172,6 +172,8 @@ class ClientEntry {
tag.css("cursor", "pointer");
tag.css("font-weight", "bold");
tag.css("color", "darkblue");
tag.css("display", "table");
if(braces)
tag.text("\"" + name + "\"");
else

View file

@ -0,0 +1,88 @@
/// <reference path="../../utils/modal.ts" />
namespace Modals {
export function spawnConnectModal(defaultHost: string = "ts.TeaSpeak.de") {
const connectModal = createModal({
header: function() {
let header = $.spawn("div");
header.text("Create a new connection");
return header;
},
body: function () {
let tag = $("#tmpl_connect").contents().clone();
let updateFields = function () {
let button = tag.parents(".modal-content").find(".connect_connect_button");
let field_address = tag.find(".connect_address");
let address = field_address.val().toString();
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.DOMAIN);
let field_nickname = tag.find(".connect_nickname");
let nickname = field_nickname.val().toString();
let flag_nickname = nickname.length >= 3 && nickname.length <= 32;
if(flag_address) {
if(field_address.hasClass("invalid_input"))
field_address.removeClass("invalid_input");
} else {
if(!field_address.hasClass("invalid_input"))
field_address.addClass("invalid_input");
}
if(flag_nickname) {
if(field_nickname.hasClass("invalid_input"))
field_nickname.removeClass("invalid_input");
} else {
if(!field_nickname.hasClass("invalid_input"))
field_nickname.addClass("invalid_input");
}
if(!flag_nickname || !flag_address) {
button.attr("disabled", "true");
} else {
button.removeAttr("disabled");
}
}
tag.find(".connect_address").val(defaultHost);
tag.find(".connect_address").on("keyup", () => updateFields());
tag.find(".connect_nickname").on("keyup", () => updateFields());
//connect_address
return tag;
},
footer: function () {
let tag = $.spawn("div");
tag.css("text-align", "right");
tag.css("margin-top", "3px");
tag.css("margin-bottom", "6px");
tag.addClass("modal-button-group");
let button = $.spawn("button");
button.addClass("connect_connect_button");
button.text("Connect");
button.on("click", function () {
connectModal.close();
let field_address = tag.parents(".modal-content").find(".connect_address");
let address = field_address.val().toString();
globalClient.startConnection(address);
});
tag.append(button);
return tag;
},
width: 600,
//closeable: false
});
connectModal.open();
}
}
let Regex = {
//DOMAIN<:port>
DOMAIN: /^(localhost|((([a-zA-Z0-9_-]{0,63}\.){0,253})?[a-zA-Z0-9_-]{0,63}\.[a-zA-Z]{2,5}))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
//IP<:port>
IP_V4: /(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
IP_V6: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/,
IP: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
};

View file

@ -0,0 +1,40 @@
/// <reference path="../../utils/modal.ts" />
namespace Modals {
export function createChannelModal(channel?: ChannelEntry) {
const modal = createModal({
header: "Create channel",
body: () => {
let template = $("#tmpl_channel_edit").tmpl({
channel_name: "Hello World",
myArray: [
"A",
"B",
"C"
]
});
template = $.spawn("div").append(template);
let tag = template.tabify();
return tag;
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
let buttonCancel = $.spawn("button");
buttonCancel.text("Cancel");
let buttonOk = $.spawn("button");
buttonOk.text("Ok");
footer.append(buttonCancel);
footer.append(buttonOk);
return footer;
},
width: 500
});
}
}

View file

@ -0,0 +1,86 @@
/// <reference path="../../utils/modal.ts" />
/// <reference path="../../utils/tab.ts" />
/// <reference path="../../proto.ts" />
namespace Modals {
export function spawnSettingsModal() {
const modal = createModal({
header: "Settings",
body: () => {
let template = $("#tmpl_settings").tmpl();
template = $.spawn("div").append(template);
initialiseSettingListeners(template = template.tabify());
return template;
},
footer: () => {
let footer = $.spawn("div");
footer.addClass("modal-button-group");
footer.css("margin-top", "5px");
footer.css("margin-bottom", "5px");
footer.css("text-align", "right");
let buttonOk = $.spawn("button");
buttonOk.text("Ok");
buttonOk.click(() => modal.close());
footer.append(buttonOk);
return footer;
},
width: 750
});
modal.open();
}
function initialiseSettingListeners(tag: JQuery) {
//Voice
initialiseVoiceListeners(tag.find(".settings_voice"));
}
function initialiseVoiceListeners(tag: JQuery) {
let currentVAD = globalClient.settings.global("vad_type");
tag.find("input[type=radio][name=\"vad_type\"]").change(function (this: HTMLButtonElement) {
console.log(this.value + " => " + $(this).attr("display"));
tag.find(".vad_settings .vad_type").text($(this).attr("display"));
tag.find(".vad_settings .vad_type_settings").hide();
tag.find(".vad_settings .vad_type_" + this.value).show();
globalClient.settings.changeGlobal("vad_type", this.value);
globalClient.voiceConnection.voiceRecorder.reinizaliszeVAD();
switch (this.value) {
case "ppt":
let keyCode: number = Number.parseInt(globalClient.settings.global("vad_ppt_key", Key.T.toString()));
tag.find(".vat_ppt_key").text(String.fromCharCode(keyCode));
}
});
if(!currentVAD)
currentVAD = "ppt";
let elm = tag.find("input[type=radio][name=\"vad_type\"][value=\"" + currentVAD + "\"]");
elm.attr("checked", "true");
elm.trigger("change");
tag.find(".vat_ppt_key").click(function () {
let modal = createModal({
body: "",
header: () => {
let head = $.spawn("div");
head.text("Type the key you wish");
head.css("background-color", "blue");
console.log("SPAWNED!");
return head;
},
footer: ""
});
$(document).one("keypress", function (e) {
console.log("Got key " + e.keyCode);
modal.close();
globalClient.settings.changeGlobal("vad_ppt_key", e.keyCode.toString());
globalClient.voiceConnection.voiceRecorder.reinizaliszeVAD();
tag.find(".vat_ppt_key").text(String.fromCharCode(e.keyCode));
});
modal.open();
});
}
}

View file

@ -21,7 +21,7 @@ class ServerEntry {
get htmlTag() {
if (this._htmlTag)
return this._htmlTag;
var tag = $("<div></div>");
let tag = $.spawn("div");
tag.attr("id", "server");
tag.addClass("server");
tag.append("<div class=\"icon client-server_green\"></div>");

View file

@ -1 +1 @@
{"version":3,"file":"server.js","sourceRoot":"","sources":["server.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"server.js","sourceRoot":"","sources":["server.ts"],"names":[],"mappings":"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"}

View file

@ -28,7 +28,7 @@ class ServerEntry {
get htmlTag() {
if(this._htmlTag) return this._htmlTag;
var tag = $("<div></div>")
let tag = $.spawn("div");
tag.attr("id", "server");
tag.addClass("server");

View file

@ -1,4 +1,4 @@
/// <reference path="../voice.ts" />
/// <reference path="../voice/VoiceHandler.ts" />
/// <reference path="../client.ts" />
/// <reference path="../contextMenu.ts" />
/// <reference path="../proto.ts" />
@ -8,12 +8,11 @@ class ChannelTree {
constructor(client, htmlTree) {
this.client = client;
this.htmlTree = htmlTree;
this.server = new ServerEntry(this, "undefined");
this.channels = [];
this.clients = [];
let jhtml = $(this.htmlTree);
jhtml.empty();
this.server.htmlTag.appendTo(jhtml);
this.reset();
}
initialiseHead(serverName) {
this.server = new ServerEntry(this, serverName);
this.server.htmlTag.appendTo(this.htmlTree);
this.server.initializeListener();
}
__deleteAnimation(element) {
@ -56,8 +55,8 @@ class ChannelTree {
let tag = this.htmlTree;
let prevChannel = null;
if (channel.hasParent()) {
var parent = channel.parentChannel();
var siblings = parent.siblings();
let parent = channel.parentChannel();
let siblings = parent.siblings();
if (siblings.length == 0) {
elm = parent.htmlTag;
prevChannel = null;
@ -83,11 +82,6 @@ class ChannelTree {
return this.channels[index];
return undefined;
}
/**
* @param {ChannelEntry} channel
* @param {ChannelEntry} prevChannel
* @param {ChannelEntry} parent
*/
moveChannel(channel, prevChannel, parent) {
if (prevChannel != null && prevChannel.parent != parent) {
console.error("Invalid channel move (different parents! (" + prevChannel.parent + "|" + parent + ")");
@ -131,7 +125,7 @@ class ChannelTree {
this.clients.push(client);
client.channelTree = this;
client["_channel"] = channel;
var tag = client.htmlTag.css({ display: "none" }).fadeIn("slow");
let tag = client.htmlTag.css({ display: "none" }).fadeIn("slow");
tag.appendTo(channel.clientTag());
channel.adjustSize(true);
client.initializeListener();
@ -187,5 +181,11 @@ class ChannelTree {
}
return result;
}
reset() {
this.server = null;
this.clients = [];
this.channels = [];
this.htmlTree.empty();
}
}
//# sourceMappingURL=view.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
/// <reference path="../voice.ts" />
/// <reference path="../voice/VoiceHandler.ts" />
/// <reference path="../client.ts" />
/// <reference path="../contextMenu.ts" />
/// <reference path="../proto.ts" />
@ -15,13 +15,12 @@ class ChannelTree {
constructor(client, htmlTree) {
this.client = client;
this.htmlTree = htmlTree;
this.server = new ServerEntry(this, "undefined");
this.channels = [];
this.clients = [];
this.reset();
}
let jhtml = $(this.htmlTree);
jhtml.empty();
this.server.htmlTag.appendTo(jhtml);
initialiseHead(serverName: string) {
this.server = new ServerEntry(this, serverName);
this.server.htmlTag.appendTo(this.htmlTree);
this.server.initializeListener();
}
@ -66,8 +65,8 @@ class ChannelTree {
let tag = this.htmlTree;
let prevChannel = null;
if(channel.hasParent()) {
var parent = channel.parentChannel();
var siblings = parent.siblings();
let parent = channel.parentChannel();
let siblings = parent.siblings();
if(siblings.length == 0) {
elm = parent.htmlTag;
prevChannel = null;
@ -95,12 +94,7 @@ class ChannelTree {
return undefined;
}
/**
* @param {ChannelEntry} channel
* @param {ChannelEntry} prevChannel
* @param {ChannelEntry} parent
*/
moveChannel(channel, prevChannel, parent) {
moveChannel(channel: ChannelEntry, prevChannel: ChannelEntry, parent: ChannelEntry) {
if(prevChannel != null && prevChannel.parent != parent) {
console.error("Invalid channel move (different parents! (" + prevChannel.parent + "|" + parent + ")");
return;
@ -144,7 +138,7 @@ class ChannelTree {
client.channelTree = this;
client["_channel"] = channel;
var tag = client.htmlTag.css({display: "none"}).fadeIn("slow");
let tag = client.htmlTag.css({display: "none"}).fadeIn("slow");
tag.appendTo(channel.clientTag());
channel.adjustSize(true);
client.initializeListener();
@ -210,4 +204,11 @@ class ChannelTree {
return result;
}
reset(){
this.server = null;
this.clients = [];
this.channels = [];
this.htmlTree.empty();
}
}

View file

@ -15,6 +15,9 @@ const ModalFunctions = {
switch (typeof val) {
case "string": return $("<div>" + val + "</div>");
case "object": return val;
case "undefined":
console.warn("Got undefined type!");
return $.spawn("div");
default:
console.error("Invalid type " + typeof val);
return $();

File diff suppressed because one or more lines are too long

View file

@ -16,6 +16,9 @@ const ModalFunctions = {
switch (typeof val){
case "string": return $("<div>" + val + "</div>");
case "object": return val as JQuery;
case "undefined":
console.warn("Got undefined type!");
return $.spawn("div");
default:
console.error("Invalid type " + typeof val);
return $();

View file

@ -20,16 +20,26 @@ var TabFunctions = {
header.addClass("tab-header");
let content = $.spawn("div");
content.addClass("tab-content");
let silentContent = $.spawn("div");
silentContent.addClass("tab-content-invisible");
template.find("x-entry").each(function () {
let hentry = $.spawn("div");
hentry.addClass("entry");
hentry.append($(this).find("x-tag").clone());
hentry.append($(this).find("x-tag").clone(true, true));
const _this = $(this);
const _entryContent = _this.find("x-content").clone(true, true);
silentContent.append(_entryContent);
hentry.on("click", function () {
if (hentry.hasClass("selected"))
return;
tag.find(".tab-header .selected").removeClass("selected");
hentry.addClass("selected");
content.children().appendTo(silentContent);
console.log(silentContent);
content.empty();
content.append(_this.find("x-content").clone());
content.append(_entryContent);
//console.log(_this.find("x-content"));
//content.append(_this.find("x-content"));
});
console.log(this);
header.append(hentry);
@ -37,6 +47,7 @@ var TabFunctions = {
header.find(".entry").first().trigger("click");
tag.append(header);
tag.append(content);
tag.append(silentContent);
return tag;
}
};

View file

@ -1 +1 @@
{"version":3,"file":"tab.js","sourceRoot":"","sources":["tab.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"tab.js","sourceRoot":"","sources":["tab.ts"],"names":[],"mappings":"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"}

View file

@ -29,18 +29,28 @@ var TabFunctions = {
let content = $.spawn("div");
content.addClass("tab-content");
let silentContent = $.spawn("div");
silentContent.addClass("tab-content-invisible");
template.find("x-entry").each(function () {
let hentry = $.spawn("div");
hentry.addClass("entry");
hentry.append($(this).find("x-tag").clone());
hentry.append($(this).find("x-tag").clone(true, true));
const _this = $(this);
const _entryContent = _this.find("x-content").clone(true, true);
silentContent.append(_entryContent);
hentry.on("click", function () {
if(hentry.hasClass("selected")) return;
tag.find(".tab-header .selected").removeClass("selected");
hentry.addClass("selected");
content.children().appendTo(silentContent);
console.log(silentContent);
content.empty();
content.append(_this.find("x-content").clone());
content.append(_entryContent);
//console.log(_this.find("x-content"));
//content.append(_this.find("x-content"));
});
console.log(this);
@ -51,6 +61,7 @@ var TabFunctions = {
tag.append(header);
tag.append(content);
tag.append(silentContent);
return tag;
}
}

View file

@ -1,269 +0,0 @@
/// <reference path="client.ts" />
class VoiceConnection {
/*
private _voicePacketBuffer: Uint8Array[] = [];
private _voicePacketSender: NodeJS.Timer;
private _triggered = false;
*/
constructor(client) {
this.vpacketId = 0;
this.client = client;
this.voiceRecorder = new VoiceRecorder(this);
this.voiceRecorder.on_data = data => this.handleVoiceData(data);
this.codec = new OpusCodec();
this.codec.initialise();
this.codec.on_encoded_data = buffer => {
if (this.dataChannel) {
this.vpacketId++;
if (this.vpacketId > 65535)
this.vpacketId = 0;
let packet = new Uint8Array(buffer.byteLength + 2 + 3);
packet[0] = this.vpacketId < 6 ? 1 : 0; //Flag header
packet[1] = 0; //Flag fragmented
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
packet[4] = 4; //Codec
packet.set(buffer, 5);
//this._voicePacketBuffer.push(packet);
this.dataChannel.send(packet);
}
};
/*
this._voicePacketSender = setInterval(() => {
if(this._voicePacketBuffer.length > 5 || this._triggered) {
let packet = this._voicePacketBuffer.pop_front();
if (packet) {
this.dataChannel.send(packet);
}
this._triggered = this._voicePacketBuffer.length > 0;
}
}, 20);
*/
}
createSession() {
const config = {};
this.rtcPeerConnection = new RTCPeerConnection(config);
const dataChannelConfig = { ordered: false, maxRetransmits: 0 };
this.dataChannel = this.rtcPeerConnection.createDataChannel('main', dataChannelConfig);
this.dataChannel.onmessage = this.onDataChannelMessage.bind(this);
this.dataChannel.onopen = this.onDataChannelOpen.bind(this);
this.dataChannel.binaryType = "arraybuffer";
let sdpConstraints = {};
sdpConstraints.offerToReceiveAudio = 0;
sdpConstraints.offerToReceiveVideo = 0;
this.rtcPeerConnection.onicecandidate = this.onIceCandidate.bind(this);
this.rtcPeerConnection.createOffer(this.onOfferCreated.bind(this), () => {
console.error("Could not create ice offer!");
}, sdpConstraints);
}
dropSession() {
this.dataChannel.close();
this.rtcPeerConnection.close();
//TODO here!
}
handleControlPacket(json) {
if (json["request"] === "create") {
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription({ type: "answer", sdp: json["sdp"] }));
}
else if (json["request"] === "ice") {
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate({ candidate: json["candidate"], sdpMid: json["session"], sdpMLineIndex: json["line"] }));
}
}
//Listeners
onIceCandidate(event) {
console.log("Got ice candidate! Event:");
console.log(event);
if (event && event.candidate) {
this.client.serverConnection.send(JSON.stringify({
type: 'WebRTC',
request: "ice",
candidate: event.candidate.candidate,
line: event.candidate.sdpMLineIndex,
session: event.candidate.sdpMid
}));
}
}
onOfferCreated(localSession) {
console.log("Offer created and accepted");
this.rtcPeerConnection.setLocalDescription(localSession);
this.client.serverConnection.send(JSON.stringify({ type: 'WebRTC', request: "create", session: localSession }));
}
onDataChannelOpen(channel) {
console.log("Got new data channel!");
}
onDataChannelMessage(message) {
let bin = new Uint8Array(message.data);
let clientId = bin[2] << 8 | bin[3];
let packetId = bin[0] << 8 | bin[1];
let codec = bin[4];
console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
let client = this.client.channelTree.findClient(clientId);
if (!client) {
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
return;
}
var encodedData = new Uint8Array(message.data, 5);
this.codec.decodeSamples(encodedData).then(buffer => client.getAudioController().play(buffer)).catch(error => {
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
});
}
handleVoiceData(data) {
setTimeout(() => {
this.codec.encodeSamples(data);
}, 1);
}
}
class VoiceRecorder {
constructor(handle) {
this.on_data = (data) => { };
this._recording = false;
this.microphoneStream = undefined;
this.mediaStream = undefined;
this.handle = handle;
this.userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
this.audioContext = new AudioContext();
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
const _this = this;
this.processor.addEventListener('audioprocess', ev => {
console.log(ev.inputBuffer);
if (_this.microphoneStream)
this.on_data(ev.inputBuffer);
});
//Not needed but make sure we have data for the preprocessor
this.mute = this.audioContext.createGain();
this.processor.connect(this.mute);
this.mute.connect(this.audioContext.destination);
}
avariable() {
return !!this.userMedia;
}
update(flag) {
if (this._recording == flag)
return;
if (flag)
this.start();
else
this.stop();
}
start() {
console.log("Attempt recording!");
this._recording = true;
this.userMedia({ audio: true }, this.on_microphone.bind(this), error => {
createErrorModal("Could not resolve microphone!", "Could not resolve microphone!<br>Message: " + error).open();
console.error("Could not get microphone!");
console.error(error);
});
}
stop() {
console.log("Stop recording!");
this._recording = false;
if (this.microphoneStream)
this.microphoneStream.disconnect();
this.microphoneStream = undefined;
if (this.mediaStream) {
if (this.mediaStream.stop)
this.mediaStream.stop();
else
this.mediaStream.getTracks().forEach(value => {
value.stop();
});
}
this.mediaStream = undefined;
}
on_microphone(stream) {
if (this.microphoneStream) {
this.stop(); //Disconnect old stream
}
console.log("Start recording!");
this.mediaStream = stream;
this.microphoneStream = this.audioContext.createMediaStreamSource(stream);
this.microphoneStream.connect(this.processor);
}
}
VoiceRecorder.CHANNEL = 0;
VoiceRecorder.CHANNELS = 1;
VoiceRecorder.BUFFER_SIZE = 16384 / 2;
class AudioController {
static get globalContext() {
if (this._globalContext)
return this._globalContext;
this._globalContext = new AudioContext();
return this._globalContext;
}
constructor() {
this.speakerContext = AudioController.globalContext;
this.nextTime = 0;
this.last = 0;
this.audioCache = [];
this.init = false;
this.stimeout = null;
this.onSpeaking = function () { };
this.onSilence = function () { };
}
play(buffer) {
if (buffer.sampleRate != this.speakerContext.sampleRate)
console.warn("[AudioController] Source sample rate isnt equal to playback sample rate!");
this.audioCache.push(buffer);
let currentTime = new Date().getTime();
if ((currentTime - this.last) > 50) {
this.init = false;
this.nextTime = 0;
console.log("[Audio] New data");
}
this.last = currentTime;
// make sure we put at least 5 chunks in the buffer before starting
if ((this.init === true) || ((this.init === false) && (this.audioCache.length > 5))) {
if (this.init === false) {
this.onSpeaking();
}
this.init = true;
this.playCache(this.audioCache);
}
this.triggerTimeout();
}
;
playCache(cache) {
while (cache.length) {
let buffer = cache.shift();
let source = this.speakerContext.createBufferSource();
source.buffer = buffer;
source.connect(this.speakerContext.destination);
if (this.nextTime == 0) {
// add a delay of 0.05 seconds
console.log("New next time!");
this.nextTime = this.speakerContext.currentTime + .05;
}
source.start(this.nextTime);
this.nextTime += source.buffer.duration;
}
}
;
triggerTimeout() {
if (this.stimeout)
clearTimeout(this.stimeout);
this.stimeout = setTimeout(function (_this) {
_this.onSilence();
_this.stimeout = null;
}, 50, this);
}
close() {
clearTimeout(this.stimeout);
}
}
class Resampler {
constructor(targetSampleRate = 44100) {
this.targetSampleRate = targetSampleRate;
}
resample(buffer) {
if (buffer.sampleRate == this.targetSampleRate)
return new Promise(resolve => resolve(buffer));
console.log(this.targetSampleRate);
let context = new OfflineAudioContext(1, Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate), this.targetSampleRate);
let source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
return context.startRendering();
}
}
//# sourceMappingURL=voice.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,335 +0,0 @@
/// <reference path="client.ts" />
class VoiceConnection {
client: TSClient;
rtcPeerConnection: RTCPeerConnection;
dataChannel: RTCDataChannel;
voiceRecorder: VoiceRecorder;
start: number;
codec: Codec;
vpacketId: number = 0;
/*
private _voicePacketBuffer: Uint8Array[] = [];
private _voicePacketSender: NodeJS.Timer;
private _triggered = false;
*/
constructor(client) {
this.client = client;
this.voiceRecorder = new VoiceRecorder(this);
this.voiceRecorder.on_data = data => this.handleVoiceData(data);
this.codec = new OpusCodec();
this.codec.initialise();
this.codec.on_encoded_data = buffer => {
if(this.dataChannel) {
this.vpacketId++;
if(this.vpacketId > 65535) this.vpacketId = 0;
let packet = new Uint8Array(buffer.byteLength + 2 + 3);
packet[0] = this.vpacketId < 6 ? 1 : 0; //Flag header
packet[1] = 0; //Flag fragmented
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
packet[4] = 4; //Codec
packet.set(buffer, 5);
//this._voicePacketBuffer.push(packet);
this.dataChannel.send(packet);
}
};
/*
this._voicePacketSender = setInterval(() => {
if(this._voicePacketBuffer.length > 5 || this._triggered) {
let packet = this._voicePacketBuffer.pop_front();
if (packet) {
this.dataChannel.send(packet);
}
this._triggered = this._voicePacketBuffer.length > 0;
}
}, 20);
*/
}
createSession() {
const config = { /*iceServers: [{ url: 'stun:stun.l.google.com:19302' }]*/ };
this.rtcPeerConnection = new RTCPeerConnection(config);
const dataChannelConfig = { ordered: false, maxRetransmits: 0 };
this.dataChannel = this.rtcPeerConnection.createDataChannel('main', dataChannelConfig);
this.dataChannel.onmessage = this.onDataChannelMessage.bind(this);
this.dataChannel.onopen = this.onDataChannelOpen.bind(this);
this.dataChannel.binaryType = "arraybuffer";
let sdpConstraints : RTCOfferOptions = {};
sdpConstraints.offerToReceiveAudio = 0;
sdpConstraints.offerToReceiveVideo = 0;
this.rtcPeerConnection.onicecandidate = this.onIceCandidate.bind(this);
this.rtcPeerConnection.createOffer(this.onOfferCreated.bind(this), () => {
console.error("Could not create ice offer!");
}, sdpConstraints);
}
dropSession() {
this.dataChannel.close();
this.rtcPeerConnection.close();
//TODO here!
}
handleControlPacket(json) {
if(json["request"] === "create") {
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription({type: "answer", sdp: json["sdp"]}));
} else if(json["request"] === "ice") {
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate({candidate: json["candidate"],sdpMid: json["session"],sdpMLineIndex: json["line"]}));
}
}
//Listeners
onIceCandidate(event) {
console.log("Got ice candidate! Event:");
console.log(event);
if (event && event.candidate) {
this.client.serverConnection.send(JSON.stringify({
type: 'WebRTC',
request: "ice",
candidate: event.candidate.candidate,
line: event.candidate.sdpMLineIndex,
session: event.candidate.sdpMid
}));
}
}
onOfferCreated(localSession) {
console.log("Offer created and accepted");
this.rtcPeerConnection.setLocalDescription(localSession);
this.client.serverConnection.send(JSON.stringify({type: 'WebRTC', request: "create", session: localSession}));
}
onDataChannelOpen(channel) {
console.log("Got new data channel!");
}
onDataChannelMessage(message) {
let bin = new Uint8Array(message.data);
let clientId = bin[2] << 8 | bin[3];
let packetId = bin[0] << 8 | bin[1];
let codec = bin[4];
console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
let client = this.client.channelTree.findClient(clientId);
if(!client) {
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
return;
}
var encodedData = new Uint8Array(message.data, 5);
this.codec.decodeSamples(encodedData).then(buffer => client.getAudioController().play(buffer)).catch(error => {
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
});
}
private handleVoiceData(data: AudioBuffer) {
setTimeout(() => {
this.codec.encodeSamples(data);
}, 1);
}
}
class VoiceRecorder {
private static readonly CHANNEL = 0;
private static readonly CHANNELS = 1;
private static readonly BUFFER_SIZE = 16384 / 2;
handle: VoiceConnection;
on_data: (data: AudioBuffer) => void = (data) => {};
private _recording: boolean = false;
private userMedia: any;
private microphoneStream: MediaStreamAudioSourceNode = undefined;
private mediaStream: MediaStream = undefined;
private audioContext: AudioContext
private processor: any;
private mute: any;
constructor(handle: VoiceConnection) {
this.handle = handle;
this.userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
this.audioContext = new AudioContext();
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
const _this = this;
this.processor.addEventListener('audioprocess', ev => {
console.log(ev.inputBuffer);
if(_this.microphoneStream)
this.on_data(ev.inputBuffer)
});
//Not needed but make sure we have data for the preprocessor
this.mute = this.audioContext.createGain();
this.processor.connect(this.mute);
this.mute.connect(this.audioContext.destination);
}
avariable() : boolean {
return !!this.userMedia;
}
update(flag: boolean) {
if(this._recording == flag) return;
if(flag) this.start();
else this.stop();
}
start(){
console.log("Attempt recording!");
this._recording = true;
this.userMedia({audio: true}, this.on_microphone.bind(this), error => {
createErrorModal("Could not resolve microphone!", "Could not resolve microphone!<br>Message: " + error).open();
console.error("Could not get microphone!");
console.error(error);
});
}
stop(){
console.log("Stop recording!");
this._recording = false;
if(this.microphoneStream) this.microphoneStream.disconnect();
this.microphoneStream = undefined;
if(this.mediaStream) {
if(this.mediaStream.stop)
this.mediaStream.stop();
else
this.mediaStream.getTracks().forEach(value => {
value.stop();
});
}
this.mediaStream = undefined;
}
private on_microphone(stream: MediaStream) {
if(this.microphoneStream) {
this.stop(); //Disconnect old stream
}
console.log("Start recording!");
this.mediaStream = stream as MediaStream;
this.microphoneStream = this.audioContext.createMediaStreamSource(stream);
this.microphoneStream.connect(this.processor);
}
}
class AudioController {
private static _globalContext;
static get globalContext() : AudioContext {
if(this._globalContext) return this._globalContext;
this._globalContext = new AudioContext();
return this._globalContext;
}
speakerContext: AudioContext;
nextTime: number;
last: number;
audioCache: AudioBuffer[];
init: boolean;
stimeout: NodeJS.Timer;
//Events
onSpeaking: () => void;
onSilence: () => void;
constructor() {
this.speakerContext = AudioController.globalContext;
this.nextTime = 0;
this.last = 0;
this.audioCache = [];
this.init = false;
this.stimeout = null;
this.onSpeaking = function () { }
this.onSilence = function () { }
}
play(buffer: AudioBuffer) {
if(buffer.sampleRate != this.speakerContext.sampleRate)
console.warn("[AudioController] Source sample rate isnt equal to playback sample rate!");
this.audioCache.push(buffer);
let currentTime = new Date().getTime();
if((currentTime - this.last) > 50) {
this.init = false;
this.nextTime = 0;
console.log("[Audio] New data");
}
this.last = currentTime;
// make sure we put at least 5 chunks in the buffer before starting
if ((this.init === true) || ((this.init === false) && (this.audioCache.length > 5))) {
if(this.init === false) {
this.onSpeaking();
}
this.init = true;
this.playCache(this.audioCache);
}
this.triggerTimeout();
};
playCache(cache) {
while (cache.length) {
let buffer = cache.shift();
let source = this.speakerContext.createBufferSource();
source.buffer = buffer;
source.connect(this.speakerContext.destination);
if (this.nextTime == 0) {
// add a delay of 0.05 seconds
console.log("New next time!");
this.nextTime = this.speakerContext.currentTime + .05;
}
source.start(this.nextTime);
this.nextTime += source.buffer.duration;
}
};
triggerTimeout(){
if(this.stimeout) clearTimeout(this.stimeout);
this.stimeout = setTimeout(function (_this) {
_this.onSilence();
_this.stimeout = null;
}, 50, this);
}
close(){
clearTimeout(this.stimeout);
}
}
class Resampler {
targetSampleRate: number;
constructor(targetSampleRate: number = 44100){
this.targetSampleRate = targetSampleRate;
}
resample(buffer: AudioBuffer) : Promise<AudioBuffer> {
if(buffer.sampleRate == this.targetSampleRate)
return new Promise<AudioBuffer>(resolve => resolve(buffer));
console.log(this.targetSampleRate);
let context = new OfflineAudioContext(1, Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate), this.targetSampleRate);
let source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
return context.startRendering();
}
}

View file

@ -0,0 +1,96 @@
class AudioController {
private static _globalContext;
static get globalContext() : AudioContext {
if(this._globalContext) return this._globalContext;
this._globalContext = new AudioContext();
return this._globalContext;
}
speakerContext: AudioContext;
nextTime: number;
last: number;
audioCache: AudioBuffer[];
init: boolean;
private _audioStopped: boolean = true;
//Events
onSpeaking: () => void;
onSilence: () => void;
constructor() {
this.speakerContext = AudioController.globalContext;
this.nextTime = 0;
this.last = 0;
this.audioCache = [];
this.init = false;
this.onSpeaking = function () { };
this.onSilence = function () { };
}
play(buffer: AudioBuffer) {
if (buffer.sampleRate != this.speakerContext.sampleRate)
console.warn("[AudioController] Source sample rate isn't equal to playback sample rate!");
this.audioCache.push(buffer);
let currentTime = new Date().getTime();
if (this._audioStopped && !this.init) {
this.nextTime = 0;
this.init = true;
console.log("[Audio] New data");
}
this.last = currentTime;
if (this.init && this.audioCache.length > 5) {
this.onSpeaking();
this.playCache(this.audioCache);
this.init = false;
console.log("[Audio] Prebuffering succeeded (Replaying now)");
} else if (!this.init) {
this.playCache(this.audioCache);
}
}
private _playingSources: AudioBufferSourceNode[] = [];
playCache(cache) {
while (cache.length) {
let buffer = cache.shift();
let source = this.speakerContext.createBufferSource();
source.buffer = buffer;
source.connect(this.speakerContext.destination);
source.onended = () => {
this._playingSources.remove(source);
this.testPlayback();
};
if (this.nextTime == 0) {
this._audioStopped = false;
this.nextTime = this.speakerContext.currentTime;
console.log("New next time!");
}
source.start(this.nextTime);
this.nextTime += source.buffer.duration;
this._playingSources.push(source);
}
};
stopAudio(now: boolean = false) {
if(now) {
for(let e of this._playingSources)
e.stop();
this._playingSources = [];
this.testPlayback();
}
}
private testPlayback() {
if(this._playingSources.length == 0) {
this.onSilence();
this._audioStopped = true;
}
}
close(){
}
}

View file

@ -0,0 +1,22 @@
class AudioResampler {
targetSampleRate: number;
constructor(targetSampleRate: number = 44100){
this.targetSampleRate = targetSampleRate;
}
resample(buffer: AudioBuffer) : Promise<AudioBuffer> {
if(buffer.sampleRate == this.targetSampleRate)
return new Promise<AudioBuffer>(resolve => resolve(buffer));
let context;
context = new OfflineAudioContext(1, Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate), this.targetSampleRate);
let source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
return context.startRendering();
}
}

141
js/voice/VoiceHandler.js Normal file
View file

@ -0,0 +1,141 @@
/// <reference path="../client.ts" />
/// <reference path="VoiceRecorder.ts" />
class VoiceConnection {
constructor(client) {
this.codecs = [
undefined,
undefined,
undefined,
undefined,
undefined,
undefined //opus music
];
this.vpacketId = 0;
this.chunkVPacketId = 0;
this.client = client;
this.voiceRecorder = new VoiceRecorder(this);
this.voiceRecorder.on_data = this.handleVoiceData.bind(this);
this.voiceRecorder.on_end = this.handleVoiceEnded.bind(this);
this.codecs[4] = new OpusCodec(1, OpusType.VOIP);
this.codecs[5] = new OpusCodec(2, OpusType.AUDIO);
for (let index = 0; index < this.codecs.length; index++) {
if (!this.codecs[index])
continue;
let codec = this.codecs[index];
console.log("Got codec " + codec.name());
codec.initialise();
codec.on_encoded_data = buffer => this.sendVoicePacket(buffer, index);
}
}
sendVoicePacket(data, codec) {
if (this.dataChannel) {
this.vpacketId++;
if (this.vpacketId > 65535)
this.vpacketId = 0;
let packet = new Uint8Array(data.byteLength + 2 + 3);
packet[0] = this.chunkVPacketId++ < 5 ? 1 : 0; //Flag header
packet[1] = 0; //Flag frag mented
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
packet[4] = codec; //Codec
packet.set(data, 5);
this.dataChannel.send(packet);
}
else {
console.warn("Could not transfer audio (not connected)");
}
}
createSession() {
const config = {};
this.rtcPeerConnection = new RTCPeerConnection(config);
const dataChannelConfig = { ordered: false, maxRetransmits: 0 };
this.dataChannel = this.rtcPeerConnection.createDataChannel('main', dataChannelConfig);
this.dataChannel.onmessage = this.onDataChannelMessage.bind(this);
this.dataChannel.onopen = this.onDataChannelOpen.bind(this);
this.dataChannel.binaryType = "arraybuffer";
let sdpConstraints = {};
sdpConstraints.offerToReceiveAudio = 0;
sdpConstraints.offerToReceiveVideo = 0;
this.rtcPeerConnection.onicecandidate = this.onIceCandidate.bind(this);
this.rtcPeerConnection.createOffer(this.onOfferCreated.bind(this), () => {
console.error("Could not create ice offer!");
}, sdpConstraints);
}
dropSession() {
if (this.dataChannel)
this.dataChannel.close();
if (this.rtcPeerConnection)
this.rtcPeerConnection.close();
//TODO here!
}
handleControlPacket(json) {
if (json["request"] === "create") {
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription({ type: "answer", sdp: json["sdp"] }));
}
else if (json["request"] === "ice") {
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate({ candidate: json["candidate"], sdpMid: json["session"], sdpMLineIndex: json["line"] }));
}
}
//Listeners
onIceCandidate(event) {
console.log("Got ice candidate! Event:");
console.log(event);
if (event && event.candidate) {
this.client.serverConnection.sendData(JSON.stringify({
type: 'WebRTC',
request: "ice",
candidate: event.candidate.candidate,
line: event.candidate.sdpMLineIndex,
session: event.candidate.sdpMid
}));
}
}
onOfferCreated(localSession) {
console.log("Offer created and accepted");
this.rtcPeerConnection.setLocalDescription(localSession);
this.client.serverConnection.sendData(JSON.stringify({ type: 'WebRTC', request: "create", session: localSession }));
}
onDataChannelOpen(channel) {
console.log("Got new data channel!");
}
onDataChannelMessage(message) {
let bin = new Uint8Array(message.data);
let clientId = bin[2] << 8 | bin[3];
let packetId = bin[0] << 8 | bin[1];
let codec = bin[4];
//console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
let client = this.client.channelTree.findClient(clientId);
if (!client) {
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
return;
}
if (!this.codecs[codec]) {
console.error("Could not playback codec " + codec);
return;
}
let encodedData;
if (message.data.subarray)
encodedData = message.data.subarray(5);
else
encodedData = new Uint8Array(message.data, 5);
this.codecs[codec].decodeSamples(encodedData).then(buffer => {
client.getAudioController().play(buffer);
}).catch(error => {
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
});
}
handleVoiceData(data, head) {
if (head) {
this.chunkVPacketId = 0;
this.client.getClient().speaking = true;
}
this.codecs[4].encodeSamples(data); //TODO Use channel codec!
//this.client.getClient().getAudioController().play(data);
}
handleVoiceEnded() {
console.log("Voice ended");
this.client.getClient().speaking = false;
//TODO!
}
}
//# sourceMappingURL=VoiceHandler.js.map

File diff suppressed because one or more lines are too long

160
js/voice/VoiceHandler.ts Normal file
View file

@ -0,0 +1,160 @@
/// <reference path="../client.ts" />
/// <reference path="VoiceRecorder.ts" />
class VoiceConnection {
client: TSClient;
rtcPeerConnection: RTCPeerConnection;
dataChannel: RTCDataChannel;
voiceRecorder: VoiceRecorder;
private codecs: Codec[] = [
undefined, //Spex
undefined, //Spex
undefined, //Spex
undefined, //CELT Mono
undefined, //opus voice
undefined //opus music
];
private vpacketId: number = 0;
private chunkVPacketId: number = 0;
constructor(client) {
this.client = client;
this.voiceRecorder = new VoiceRecorder(this);
this.voiceRecorder.on_data = this.handleVoiceData.bind(this);
this.voiceRecorder.on_end = this.handleVoiceEnded.bind(this);
this.codecs[4] = new OpusCodec(1, OpusType.VOIP);
this.codecs[5] = new OpusCodec(2, OpusType.AUDIO);
for(let index = 0; index < this.codecs.length; index++) {
if(!this.codecs[index]) continue;
let codec = this.codecs[index];
console.log("Got codec " + codec.name());
codec.initialise();
codec.on_encoded_data = buffer => this.sendVoicePacket(buffer, index);
}
}
sendVoicePacket(data: Uint8Array, codec: number) {
if(this.dataChannel) {
this.vpacketId++;
if(this.vpacketId > 65535) this.vpacketId = 0;
let packet = new Uint8Array(data.byteLength + 2 + 3);
packet[0] = this.chunkVPacketId++ < 5 ? 1 : 0; //Flag header
packet[1] = 0; //Flag frag mented
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
packet[4] = codec; //Codec
packet.set(data, 5);
this.dataChannel.send(packet);
} else {
console.warn("Could not transfer audio (not connected)");
}
}
createSession() {
const config = { /*iceServers: [{ url: 'stun:stun.l.google.com:19302' }]*/ };
this.rtcPeerConnection = new RTCPeerConnection(config);
const dataChannelConfig = { ordered: false, maxRetransmits: 0 };
this.dataChannel = this.rtcPeerConnection.createDataChannel('main', dataChannelConfig);
this.dataChannel.onmessage = this.onDataChannelMessage.bind(this);
this.dataChannel.onopen = this.onDataChannelOpen.bind(this);
this.dataChannel.binaryType = "arraybuffer";
let sdpConstraints : RTCOfferOptions = {};
sdpConstraints.offerToReceiveAudio = 0;
sdpConstraints.offerToReceiveVideo = 0;
this.rtcPeerConnection.onicecandidate = this.onIceCandidate.bind(this);
this.rtcPeerConnection.createOffer(this.onOfferCreated.bind(this), () => {
console.error("Could not create ice offer!");
}, sdpConstraints);
}
dropSession() {
if(this.dataChannel) this.dataChannel.close();
if(this.rtcPeerConnection) this.rtcPeerConnection.close();
//TODO here!
}
handleControlPacket(json) {
if(json["request"] === "create") {
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription({type: "answer", sdp: json["sdp"]}));
} else if(json["request"] === "ice") {
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate({candidate: json["candidate"],sdpMid: json["session"],sdpMLineIndex: json["line"]}));
}
}
//Listeners
onIceCandidate(event) {
console.log("Got ice candidate! Event:");
console.log(event);
if (event && event.candidate) {
this.client.serverConnection.sendData(JSON.stringify({
type: 'WebRTC',
request: "ice",
candidate: event.candidate.candidate,
line: event.candidate.sdpMLineIndex,
session: event.candidate.sdpMid
}));
}
}
onOfferCreated(localSession) {
console.log("Offer created and accepted");
this.rtcPeerConnection.setLocalDescription(localSession);
this.client.serverConnection.sendData(JSON.stringify({type: 'WebRTC', request: "create", session: localSession}));
}
onDataChannelOpen(channel) {
console.log("Got new data channel!");
}
onDataChannelMessage(message) {
let bin = new Uint8Array(message.data);
let clientId = bin[2] << 8 | bin[3];
let packetId = bin[0] << 8 | bin[1];
let codec = bin[4];
//console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
let client = this.client.channelTree.findClient(clientId);
if(!client) {
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
return;
}
if(!this.codecs[codec]) {
console.error("Could not playback codec " + codec);
return;
}
let encodedData;
if(message.data.subarray)
encodedData = message.data.subarray(5);
else encodedData = new Uint8Array(message.data, 5);
this.codecs[codec].decodeSamples(encodedData).then(buffer => {
client.getAudioController().play(buffer);
}).catch(error => {
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
});
}
private handleVoiceData(data: AudioBuffer, head: boolean) {
if(head) {
this.chunkVPacketId = 0;
this.client.getClient().speaking = true;
}
this.codecs[4].encodeSamples(data); //TODO Use channel codec!
//this.client.getClient().getAudioController().play(data);
}
private handleVoiceEnded() {
console.log("Voice ended");
this.client.getClient().speaking = false;
//TODO!
}
}

189
js/voice/VoiceRecorder.ts Normal file
View file

@ -0,0 +1,189 @@
/// <reference path="VoiceHandler.ts" />
/// <reference path="../utils/modal.ts" />
abstract class VoiceActivityDetector {
abstract shouldRecord(buffer: AudioBuffer) : boolean;
initialise(handle: VoiceRecorder) {}
finalize() {}
}
class VoiceRecorder {
private static readonly CHANNEL = 0;
private static readonly CHANNELS = 1;
private static readonly BUFFER_SIZE = 1024;
handle: VoiceConnection;
on_data: (data: AudioBuffer, head: boolean) => void = (data) => {};
on_end: () => void = () => {};
private _recording: boolean = false;
private userMedia: any;
private microphoneStream: MediaStreamAudioSourceNode = undefined;
private mediaStream: MediaStream = undefined;
private audioContext: AudioContext;
private processor: any;
private mute: any;
private vadHandler: VoiceActivityDetector;
private _chunkCount: number = 0;
constructor(handle: VoiceConnection) {
this.handle = handle;
this.userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
this.audioContext = new AudioContext();
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
const _this = this;
this.processor.addEventListener('audioprocess', ev => {
if(_this.microphoneStream && this.vadHandler.shouldRecord(ev.inputBuffer))
this.on_data(ev.inputBuffer, this._chunkCount++ == 0);
else {
if(this._chunkCount != 0) this.on_end();
this._chunkCount = 0
};
});
//Not needed but make sure we have data for the preprocessor
this.mute = this.audioContext.createGain();
this.processor.connect(this.mute);
this.mute.connect(this.audioContext.destination);
//this.setVADHander(new MuteVAD());
this.setVADHander(new PassThroughVAD());
}
avariable() : boolean {
return !!this.userMedia;
}
reinizaliszeVAD() {
let type = this.handle.client.settings.global("vad_type", "ppt");
if(type == "ppt") {
let keyCode: number = Number.parseInt(globalClient.settings.global("vad_ppt_key", Key.T.toString()));
if(!(this.getVADHandler() instanceof PushToTalkVAD))
this.setVADHander(new PushToTalkVAD(keyCode));
else (this.getVADHandler() as PushToTalkVAD).key = keyCode;
} else if(type == "pt") {
if(!(this.getVADHandler() instanceof PassThroughVAD))
this.setVADHander(new PassThroughVAD());
} else {
console.warn("Invalid VAD handler! (" + type + ")");
}
}
setVADHander(handler: VoiceActivityDetector) {
if(this.vadHandler) this.vadHandler.finalize();
this.vadHandler = handler;
this.vadHandler.initialise(this);
}
getVADHandler() : VoiceActivityDetector {
return this.vadHandler;
}
update(flag: boolean) {
if(this._recording == flag) return;
if(flag) this.start();
else this.stop();
}
start(){
console.log("Attempt recording!");
this._recording = true;
this.userMedia({audio: true}, this.on_microphone.bind(this), error => {
createErrorModal("Could not resolve microphone!", "Could not resolve microphone!<br>Message: " + error).open();
console.error("Could not get microphone!");
console.error(error);
});
}
stop(){
console.log("Stop recording!");
this._recording = false;
if(this.microphoneStream) this.microphoneStream.disconnect();
this.microphoneStream = undefined;
if(this.mediaStream) {
if(this.mediaStream.stop)
this.mediaStream.stop();
else
this.mediaStream.getTracks().forEach(value => {
value.stop();
});
}
this.mediaStream = undefined;
}
private on_microphone(stream: MediaStream) {
if(this.microphoneStream) {
this.stop(); //Disconnect old stream
}
console.log("Start recording!");
this.mediaStream = stream as MediaStream;
this.microphoneStream = this.audioContext.createMediaStreamSource(stream);
this.microphoneStream.connect(this.processor);
}
}
class MuteVAD extends VoiceActivityDetector {
shouldRecord(buffer: AudioBuffer): boolean {
return false;
}
}
class PassThroughVAD extends VoiceActivityDetector {
shouldRecord(buffer: AudioBuffer): boolean {
return true;
}
}
class PushToTalkVAD extends VoiceActivityDetector {
private _key: number;
private _pushed: boolean = false;
private _evListenerDown = (e: KeyboardEvent) => {
//console.log("Down -> " + e.key + " -> " + e.keyCode);
if(e.key == String.fromCharCode(this._key))
this.pushed = true;
};
private _evListenerUp = e => {
if(e.key == String.fromCharCode(this._key))
this.pushed = false;
};
constructor(key: any) {
super();
this._key = key;
}
initialise(handle: VoiceRecorder) {
document.addEventListener("keydown", this._evListenerDown);
document.addEventListener("keyup", this._evListenerUp);
return super.initialise(handle);
}
finalize() {
document.removeEventListener("keydown", this._evListenerDown);
document.removeEventListener("keyup", this._evListenerUp);
return super.finalize();
}
set pushed(flag: boolean) {
this._pushed = flag;
}
set key(key: number) {
this._key = key;
this._pushed = false;
}
shouldRecord(buffer: AudioBuffer): boolean {
return this._pushed;
}
}

View file

@ -2990,7 +2990,7 @@ MozillaAudioDevice = (function(_super) {
* Planned to be replaced with src.js, eventually: https://github.com/jussi-kalliokoski/src.js
*/
//JavaScript Audio Resampler (c) 2011 - Grant Galitz
//JavaScript Audio AudioResampler (c) 2011 - Grant Galitz
function Resampler(fromSampleRate, toSampleRate, channels, outputBufferSize, noReturn) {
this.fromSampleRate = fromSampleRate;
this.toSampleRate = toSampleRate;
@ -3005,7 +3005,7 @@ Resampler.prototype.initialize = function () {
if (this.fromSampleRate > 0 && this.toSampleRate > 0 && this.channels > 0) {
if (this.fromSampleRate == this.toSampleRate) {
//Setup a resampler bypass:
this.resampler = this.bypassResampler; //Resampler just returns what was passed through.
this.resampler = this.bypassResampler; //AudioResampler just returns what was passed through.
this.ratioWeight = 1;
}
else {

View file

@ -4700,8 +4700,10 @@ var Modal = function () {
}); // Adjust body padding
var actualPadding = document.body.style.paddingRight;
var calculatedPadding = $('body').css('padding-right');
$('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
var calculatedPadding = $('body')
.css('padding-right')
.data('padding-right', actualPadding)
.css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
}
};

View file

@ -446,7 +446,7 @@ var OpusWorker = function (_Event) {
var _this = possibleConstructorReturn(this, (OpusWorker.__proto__ || Object.getPrototypeOf(OpusWorker)).call(this, 'worker'));
_this.worker = new Worker('libopus/opus.min.js');
_this.worker.addEventListener('message', _this.onMessage.bind(_this));
_this.worker.addEventListener('message', _this.handleWebSocketMessage.bind(_this));
_this.worker.postMessage({
type: 'init',
config: {
@ -472,7 +472,7 @@ var OpusWorker = function (_Event) {
this.worker.postMessage(workerData);
}
}, {
key: 'onMessage',
key: 'handleWebSocketMessage',
value: function onMessage(event) {
var data = event.data;
this.dispatch('data', data.buffer);