Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
S
SHMCamStudio
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
SexHackMe
SHMCamStudio
Commits
51ee691c
Commit
51ee691c
authored
Jan 05, 2025
by
nextime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bidirectional communication and status persistance implemented
parent
9ca09ce5
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
291 additions
and
90 deletions
+291
-90
shmcamstudio
shmcamstudio
+4
-0
shmcamstudio.conf
shmcamstudio.conf
+24
-13
obs.py
shmcs/obs.py
+13
-7
panel.py
shmcs/panel.py
+54
-6
studio.py
shmcs/studio.py
+32
-9
utils.py
shmcs/utils.py
+13
-2
webpanel.py
shmcs/webpanel.py
+84
-9
index.html
templates/index.html
+67
-44
No files found.
shmcamstudio
View file @
51ee691c
...
...
@@ -37,9 +37,13 @@ config.read('shmcamstudio.conf')
# Inter thread communication
qcore
=
queue
.
Queue
()
# IN -> core application (studio.py)
qobs
=
queue
.
Queue
()
# IN -> OBS module
qweb
=
queue
.
Queue
()
# IN -> Web Panel
qpnl
=
queue
.
Queue
()
# IN -> tkinter panel
builtins
.
qcore
=
qcore
builtins
.
qobs
=
qobs
builtins
.
qweb
=
qweb
builtins
.
qpnl
=
qpnl
builtins
.
config
=
config
# Setup logging
...
...
shmcamstudio.conf
View file @
51ee691c
...
...
@@ -46,23 +46,29 @@ status.tease.enable = 5,3
[
OUTPUT
:
smstefy
]
obs
=
slut
scene
=
live
SFW
source
.
title
=
5
source
.
closed
=
4
source
.
tease
=
3
status
.
open
.
disable
=
5
,
4
,
3
status
.
close
.
disable
=
3
status
.
close
.
enable
=
5
,
4
status
.
tease
.
disable
=
4
status
.
tease
.
enable
=
5
,
3
[
OUTPUT
:
shine
]
obs
=
slut
scene
=
SHINE
source
.
title
=
4
source
.
closed
=
2
source
.
tease
=
3
status
.
open
.
disable
=
4
,
2
,
3
status
.
close
.
disable
=
3
status
.
close
.
enable
=
4
,
2
status
.
tease
.
disable
=
2
status
.
tease
.
enable
=
4
,
3
#[OUTPUT:livejasmin]
#obs = slut
#scene = LIVE JM
#source_title = 4,5
#source_closed = 3
#source_tease = 2
#status.open.disable = 2,3,4,5
##status.close.disable = 2
#status.close.enable = 3,4,5
#status.tease.disable = 3
#status.tease.enable = 2,4,5
# BUTTON:<rownum>:<button_name>
...
...
@@ -145,13 +151,18 @@ action = open_all
color
=
teal
[
BUTTON
:
3
:
scene_manual
]
title
=
SCENE
MANUAL
title
=
MANUAL
action
=
scene_manual
color
=
blue
color
.
manual
=
blue
color
.
automatic
=
red
title
.
manual
=
MANUAL
title
.
automatic
=
AUTO
feedback
=
status
[
ACTION
:
scene_manual
]
setstatus
=
manual
setstatus
=
change
[
ACTION
:
private_shine
]
...
...
@@ -179,10 +190,10 @@ execute = /usr/local/bin/smblur_stefy
#execute = /usr/local/bin/smblur_jasmin
[
ACTION
:
tease_all
]
execute
= /
usr
/
local
/
bin
/
smblur_tease
execute
= /
usr
/
local
/
bin
/
smblur_tease
all
[
ACTION
:
tease
]
execute
= /
usr
/
local
/
bin
/
smblur_tease
all
execute
= /
usr
/
local
/
bin
/
smblur_tease
[
ACTION
:
open_all
]
execute
= /
usr
/
local
/
bin
/
smblur_clean
...
...
shmcs/obs.py
View file @
51ee691c
...
...
@@ -71,10 +71,8 @@ class OBSOutput:
if
hasattr
(
self
,
'status.'
+
status
+
'.enable'
):
self
.
enable
(
getattr
(
self
,
'status.'
+
status
+
'.enable'
)
.
split
(
','
))
def
updateStatus
(
self
):
def
_
updateStatus
(
self
):
if
not
self
.
obss
.
online
:
self
.
status
=
False
logging
.
info
(
'FOUND False'
)
return
False
for
inp
in
self
.
inputs
.
keys
():
self
.
inputs
[
inp
]
=
self
.
obss
.
getInputStatus
(
self
.
scene
,
inp
)
...
...
@@ -90,13 +88,17 @@ class OBSOutput:
if
self
.
inputs
[
disabled
]:
found
=
False
if
found
:
self
.
status
=
found
logging
.
info
(
"FOUND "
+
found
)
return
found
logging
.
info
(
'FOUND False'
)
self
.
status
=
found
return
found
def
updateStatus
(
self
):
status
=
self
.
_updateStatus
()
if
self
.
status
!=
status
:
self
.
status
=
status
logging
.
info
(
'OUTPUT '
+
self
.
output
+
" FOUND "
+
str
(
self
.
status
))
self
.
obss
.
queue
.
put
({
'event'
:
'OUTPUTCHANGE'
,
'data'
:
{
'server'
:
self
.
obss
.
server
,
'output'
:
self
.
output
,
'status'
:
self
.
status
}})
return
self
.
status
def
getStatus
(
self
):
if
not
self
.
status
:
self
.
status
=
self
.
updateStatus
()
...
...
@@ -221,6 +223,10 @@ def run_obs_controller():
for
output
in
obs_outputs
.
values
():
if
output
.
obss
.
server
==
data
[
'server'
]
and
output
.
scene
==
data
[
'scene'
]
and
str
(
data
[
'source'
])
in
output
.
inputs
.
keys
():
output
.
updateStatus
()
if
event
==
'OUTPUTCHANGE'
:
#{ 'event': 'OUTPUTCHANGE', 'data': {'server': self.obss.server, 'output': self.output, 'status': self.status }}
logging
.
info
(
"OUTPUTCHANGE: output "
+
data
[
'output'
]
+
" on obs "
+
data
[
'server'
]
+
" is now "
+
str
(
data
[
'status'
]))
qcore
.
put
(
task
)
time
.
sleep
(
.01
)
...
...
shmcs/panel.py
View file @
51ee691c
...
...
@@ -71,6 +71,9 @@ def create_panel_gui():
helv36
=
tkFont
.
Font
(
family
=
'Helvetica'
,
size
=
config
.
get
(
"Tkinter"
,
"font_size"
,
fallback
=
12
),
weight
=
'bold'
)
# Interval in ms to read the queue
qinterval
=
200
# Frame for the left side
fleft
=
tk
.
Frame
(
window
)
fleft
.
pack
(
side
=
tk
.
LEFT
,
fill
=
tk
.
BOTH
,
expand
=
True
)
...
...
@@ -86,11 +89,12 @@ def create_panel_gui():
# Buttons configuration
buttons
,
numrows
=
get_buttons
()
bh
=
int
(
55
/
numrows
)
if
numrows
>
0
:
row
=
1
bframes
=
{}
outputs
=
{}
feedbacks
=
{}
while
row
<=
numrows
:
# create the frame for this row
bframes
[
row
]
=
tk
.
Frame
(
fright
)
...
...
@@ -103,15 +107,27 @@ def create_panel_gui():
col
=
0
logging
.
info
(
buttons
[
row
])
for
b
in
buttons
[
row
]
.
keys
():
command
=
None
if
config
.
has_section
(
'ACTION:'
+
buttons
[
row
][
b
][
'action'
]):
command
=
config
.
get
(
'ACTION:'
+
buttons
[
row
][
b
][
'action'
],
'execute'
,
fallback
=
None
)
setstatus
=
config
.
get
(
'ACTION:'
+
buttons
[
row
][
b
][
'action'
],
'setstatus'
,
fallback
=
None
)
#
command=None
#
if config.has_section('ACTION:'+buttons[row][b]['action']):
#
command=config.get('ACTION:'+buttons[row][b]['action'], 'execute', fallback=None)
#
setstatus=config.get('ACTION:'+buttons[row][b]['action'], 'setstatus', fallback=None)
color
=
buttons
[
row
][
b
][
'color'
]
button
=
tk
.
Button
(
bframes
[
row
],
text
=
buttons
[
row
][
b
][
'title'
],
font
=
helv36
,
width
=
bw
,
height
=
bh
,
bg
=
color
,
fg
=
"white"
,
command
=
lambda
cmd
=
command
,
sts
=
setstatus
:
run_action
(
cmd
,
sts
))
command
=
lambda
action
=
buttons
[
row
][
b
][
'action'
]:
run_action
(
action
))
#command=lambda cmd=command,sts=setstatus: run_action(cmd,sts))
button
.
grid
(
row
=
0
,
column
=
col
,
sticky
=
'nsew'
)
if
'output'
in
buttons
[
row
][
b
]
.
keys
():
outputs
[
buttons
[
row
][
b
][
'output'
]]
=
{
'btn'
:
button
,
'cfg'
:
buttons
[
row
][
b
]}
elif
'feedback'
in
buttons
[
row
][
b
]
.
keys
():
if
not
buttons
[
row
][
b
][
'feedback'
]
in
feedbacks
.
keys
():
feedbacks
[
buttons
[
row
][
b
][
'feedback'
]]
=
[{
'btn'
:
button
,
'cfg'
:
buttons
[
row
][
b
]}]
else
:
feedbacks
[
buttons
[
row
][
b
][
'feedback'
]]
.
append
({
'btn'
:
button
,
'cfg'
:
buttons
[
row
][
b
]})
col
=
col
+
1
# Configure the columns in the frame
...
...
@@ -125,5 +141,37 @@ def create_panel_gui():
bg
=
"purple"
,
fg
=
"white"
,
font
=
helv36
,
height
=
2
)
web_button
.
grid
(
row
=
1
,
column
=
1
,
sticky
=
'nsew'
)
def
read_queue
():
if
not
qpnl
.
empty
():
task
=
qpnl
.
get
(
block
=
True
)
if
task
:
logging
.
info
(
'TASK INCOMING FOR TK PANEL'
)
logging
.
info
(
task
)
event
=
task
[
'event'
]
data
=
task
[
'data'
]
if
event
==
'OUTPUTCHANGE'
:
if
data
[
'output'
]
in
outputs
.
keys
():
logging
.
info
(
'CHANGE THE COLOR OF THE BUTTON FOR '
+
str
(
data
[
'output'
]))
btn
=
outputs
[
data
[
'output'
]][
'btn'
]
bcfg
=
outputs
[
data
[
'output'
]][
'cfg'
]
if
'color.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
btn
.
config
(
bg
=
bcfg
[
'color.'
+
str
(
data
[
'status'
])])
if
'title.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
btn
.
config
(
text
=
bcfg
[
'title.'
+
str
(
data
[
'status'
])])
elif
event
==
'STATUSCHANGE'
:
if
'status'
in
feedbacks
.
keys
():
for
b
in
feedbacks
[
'status'
]:
btn
=
b
[
'btn'
]
bcfg
=
b
[
'cfg'
]
if
'color.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
btn
.
config
(
bg
=
bcfg
[
'color.'
+
str
(
data
[
'status'
])])
if
'title.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
btn
.
config
(
text
=
bcfg
[
'title.'
+
str
(
data
[
'status'
])])
window
.
after
(
qinterval
,
read_queue
)
window
.
after
(
qinterval
,
read_queue
)
# ms
return
window
shmcs/studio.py
View file @
51ee691c
...
...
@@ -22,22 +22,45 @@ logging.getLogger(__name__)
STATUSES
=
[
'manual'
,
'open'
,
'close'
'automatic'
]
class
TaskEngine
():
status
=
'init'
status
=
'manual'
scene
=
'open'
def
set_manual
(
self
,
manual
=
True
):
nst
=
False
if
manual
and
self
.
status
!=
'manual'
:
nst
=
'manual'
elif
not
manual
and
self
.
status
==
'manual'
:
nst
=
'automatic'
if
nst
:
logging
.
info
(
'CHANGE STATUS TO '
+
nst
)
self
.
status
=
nst
evt
=
{
'event'
:
'STATUSCHANGE'
,
'data'
:{
'status'
:
nst
}}
qpnl
.
put
(
evt
)
qweb
.
put
(
evt
)
def
process_task
(
self
,
task
):
cmd
,
val
=
task
.
split
(
':'
,
1
)
if
cmd
==
'SETSTATUS'
and
val
in
STATUSES
:
logging
.
info
(
'SETSTATUS TO '
+
val
)
if
self
.
status
!=
val
:
self
.
status
=
val
event
=
task
[
'event'
]
if
'data'
in
task
.
keys
():
data
=
task
[
'data'
]
if
event
==
'SETSTATUS'
and
data
[
'status'
]
in
[
'manual'
,
'automatic'
]:
if
self
.
status
!=
data
[
'status'
]:
self
.
set_manual
(
data
[
'status'
]
==
'manual'
)
elif
event
==
'CHANGESTATUS'
:
self
.
set_manual
(
self
.
status
!=
'manual'
)
#if self.status == 'manual':
# self.set_manual(False)
#else:
# self.set_manual(True)
elif
event
==
'OUTPUTCHANGE'
:
qpnl
.
put
(
task
)
qweb
.
put
(
task
)
def
camstudio
():
...
...
shmcs/utils.py
View file @
51ee691c
...
...
@@ -31,9 +31,20 @@ def run_command(command):
return
f
"Error: {e}"
def
run_action
(
command
,
setstatus
=
None
):
def
run_action
(
action
):
if
not
config
.
has_section
(
'ACTION:'
+
action
):
return
False
command
=
config
.
get
(
'ACTION:'
+
action
,
'execute'
,
fallback
=
None
)
setstatus
=
config
.
get
(
'ACTION:'
+
action
,
'setstatus'
,
fallback
=
None
)
open_outputs
=
config
.
get
(
'ACTION:'
+
action
,
'open.outputs'
,
fallback
=
None
)
if
setstatus
:
qcore
.
put
(
'SETSTATUS:'
+
str
(
setstatus
),
block
=
False
)
if
setstatus
in
[
'manual'
,
'automatic'
]:
qcore
.
put
({
'event'
:
'SETSTATUS'
,
'data'
:
{
'status'
:
setstatus
}})
elif
setstatus
in
[
'switch'
,
'change'
,
'flip'
]:
qcore
.
put
({
'event'
:
'CHANGESTATUS'
})
if
command
:
return
run_command
(
command
)
...
...
shmcs/webpanel.py
View file @
51ee691c
...
...
@@ -13,17 +13,48 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from
flask
import
Flask
,
render_template
,
request
from
flask
import
Flask
,
render_template
,
request
,
session
from
utils
import
check_port_available
,
run_command
,
create_daemon
,
run_action
import
sys
import
os
from
guiutils
import
get_buttons
import
flask_restful
as
restful
from
flask_socketio
import
SocketIO
,
emit
import
logging
logging
.
getLogger
(
__name__
)
# Flask App Setup
flask_app
=
Flask
(
'SHMCamStudio'
,
template_folder
=
TEMPLATE_DIR
)
flask_api
=
restful
.
Api
(
flask_app
)
# XXX BugFix in eventlet used in socketio
os
.
environ
[
'EVENTLET_NO_GREENDNS'
]
=
'yes'
socketio
=
SocketIO
(
flask_app
)
buttons
,
numrows
=
get_buttons
()
outputs
=
{}
feedbacks
=
{}
if
numrows
>
0
:
row
=
1
while
row
<=
numrows
:
for
b
in
buttons
[
row
]
.
keys
():
if
'output'
in
buttons
[
row
][
b
]
.
keys
():
outputs
[
buttons
[
row
][
b
][
'output'
]]
=
{
'cfg'
:
buttons
[
row
][
b
]}
elif
'feedback'
in
buttons
[
row
][
b
]
.
keys
():
if
not
buttons
[
row
][
b
][
'feedback'
]
in
feedbacks
.
keys
():
feedbacks
[
buttons
[
row
][
b
][
'feedback'
]]
=
[{
'cfg'
:
buttons
[
row
][
b
]}]
else
:
feedbacks
[
buttons
[
row
][
b
][
'feedback'
]]
.
append
({
'btn'
:
button
,
'cfg'
:
buttons
[
row
][
b
]})
row
=
row
+
1
class
PollAPI
(
restful
.
Resource
):
...
...
@@ -65,7 +96,7 @@ class AppData(restful.Resource):
@
flask_app
.
route
(
'/'
)
def
index
():
buttons
,
numrows
=
get_buttons
()
#
buttons, numrows = get_buttons()
row
=
1
style_rows
=
""
htmlbuttons
=
""
...
...
@@ -82,6 +113,8 @@ def index():
pollclass
=
''
if
'output'
in
buttons
[
row
][
b
]
.
keys
():
pollclass
=
'output_'
+
buttons
[
row
][
b
][
'output'
]
elif
'feedback'
in
buttons
[
row
][
b
]
.
keys
():
pollclass
=
'feedback_'
+
buttons
[
row
][
b
][
'feedback'
]
htmlbuttons
=
htmlbuttons
+
"""<button style="color:white;background-color:"""
+
color
+
""";"
class="button private button_row"""
+
str
(
row
)
+
" "
+
pollclass
+
""" " onclick="executeCommand('"""
+
command
+
"""')">
"""
+
buttons
[
row
][
b
][
'title'
]
+
"""
...
...
@@ -98,12 +131,7 @@ def execute():
command_key
=
request
.
form
.
get
(
'command'
)
if
config
.
has_section
(
'ACTION:'
+
command_key
):
command
=
config
.
get
(
'ACTION:'
+
command_key
,
'execute'
,
fallback
=
None
)
setstatus
=
config
.
get
(
'ACTION:'
+
command_key
,
'setstatus'
,
fallback
=
None
)
if
command
or
setstatus
:
result
=
run_action
(
command
,
setstatus
)
else
:
return
"No command available"
result
=
run_action
(
command_key
)
return
result
or
'OK'
else
:
return
"Invalid command"
,
400
...
...
@@ -115,6 +143,49 @@ def stream():
@
socketio
.
event
def
my_event
(
message
):
session
[
'receive_count'
]
=
session
.
get
(
'receive_count'
,
0
)
+
1
emit
(
'my_response'
,
{
'data'
:
message
[
'data'
],
'count'
:
session
[
'receive_count'
]})
@
socketio
.
event
def
my_ping
():
emit
(
'my_pong'
)
@
socketio
.
event
def
get_queue
():
count
=
5
while
not
qweb
.
empty
()
and
count
>
0
:
count
=
count
-
1
task
=
qweb
.
get
(
block
=
True
)
if
task
:
logging
.
info
(
'TASK INCOMING FOR WEB'
)
logging
.
info
(
task
)
event
=
task
[
'event'
]
data
=
task
[
'data'
]
if
event
==
'OUTPUTCHANGE'
:
if
data
[
'output'
]
in
outputs
.
keys
():
logging
.
info
(
'CHANGE THE COLOR OF THE WEB BUTTON FOR '
+
str
(
data
[
'output'
]))
bcfg
=
outputs
[
data
[
'output'
]][
'cfg'
]
if
'color.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
emit
(
'change_output'
,
{
'button'
:
data
[
'output'
],
'color'
:
bcfg
[
'color.'
+
str
(
data
[
'status'
])]
},
broadcast
=
True
)
if
'title.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
emit
(
'change_output'
,
{
'button'
:
data
[
'output'
],
'title'
:
bcfg
[
'title.'
+
str
(
data
[
'status'
])]
},
broadcast
=
True
)
elif
event
==
'STATUSCHANGE'
:
if
'status'
in
feedbacks
.
keys
():
for
b
in
feedbacks
[
'status'
]:
bcfg
=
b
[
'cfg'
]
if
'color.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
emit
(
'change_feedback'
,
{
'feedback'
:
'status'
,
'color'
:
bcfg
[
'color.'
+
str
(
data
[
'status'
])]
},
broadcast
=
True
)
#btn.config(bg=bcfg['color.'+str(data['status'])])
if
'title.'
+
str
(
data
[
'status'
])
in
bcfg
.
keys
():
emit
(
'change_feedback'
,
{
'feedback'
:
'status'
,
'title'
:
bcfg
[
'title.'
+
str
(
data
[
'status'
])]
},
broadcast
=
True
)
def
run_flask_app
(
port
=
5000
,
daemon_mode
=
False
):
"""Run Flask app with optional daemon mode"""
if
not
check_port_available
(
port
):
...
...
@@ -128,5 +199,9 @@ def run_flask_app(port=5000, daemon_mode=False):
flask_api
.
add_resource
(
PollAPI
,
'/update'
)
flask_api
.
add_resource
(
AppData
,
'/data'
)
flask_app
.
run
(
host
=
'0.0.0.0'
,
port
=
port
,
debug
=
False
,
use_reloader
=
False
)
#flask_app.run(host='0.0.0.0', port=port, debug=False, use_reloader=False)
# for socketio
socketio
.
run
(
flask_app
,
host
=
'0.0.0.0'
,
port
=
port
,
debug
=
True
,
use_reloader
=
False
)
templates/index.html
View file @
51ee691c
...
...
@@ -157,6 +157,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
}
}
</style>
<script
src=
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
integrity=
"sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg=="
crossorigin=
"anonymous"
></script>
<script
src=
"https://cdn.socket.io/4.7.5/socket.io.min.js"
integrity=
"sha384-2huaZvOR9iDzHqslqwpR87isEmrfxqyWOF7hr7BY6KG0+hVKLoEXMPUJw3ynWuhO"
crossorigin=
"anonymous"
></script>
</head>
<body>
<div
class=
"main-container"
>
...
...
@@ -200,13 +202,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
.
then
(
result
=>
{
console
.
log
(
result
);
// Visual feedback
event
.
target
.
style
.
backgroundColor
=
'#45a049'
;
/*
event.target.style.backgroundColor = '#45a049';
setTimeout(() => {
event.target.style.backgroundColor =
event.target.classList.contains('private') ? '#4CAF50' :
event.target.classList.contains('toggle') ? '#2196F3' :
'#FF9800';
},
300
);
}, 300);
*/
})
.
catch
(
error
=>
{
console
.
error
(
'Error:'
,
error
);
...
...
@@ -248,54 +250,75 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
document
.
addEventListener
(
'touchmove'
,
function
(
event
)
{
if
(
event
.
scale
!==
1
)
{
event
.
preventDefault
();
}
},
{
passive
:
false
});
</script>
</body>
</html>
<script>
const
sidebar
=
document
.
querySelector
(
'.sidebar'
);
const
resizeHandle
=
document
.
getElementById
(
'resize-handle'
);
const
buttonsContainer
=
document
.
querySelector
(
'.buttons-container'
);
const
containerWidth
=
document
.
querySelector
(
'.main-container'
).
clientWidth
;
$
(
document
).
ready
(
function
()
{
// Connect to the Socket.IO server.
// The connection URL has the following format, relative to the current page:
// http[s]://
<
domain
>
:
<
port
>
[
/<namespace>
]
var
socket
=
io
();
// Event handler for new connections.
// The callback function is invoked when a connection with the
// server is established.
socket
.
on
(
'connect'
,
function
()
{
socket
.
emit
(
'my_event'
,
{
data
:
'I
\'
m connected!'
});
});
function
adjustSidebarWidth
(
newWidth
)
{
sidebar
.
style
.
width
=
`
${
newWidth
}
px`
;
buttonsContainer
.
style
.
width
=
`
${
containerWidth
-
newWidth
}
px`
;
//
Notify the iframe about the resize
var
iframe
=
document
.
querySelector
(
".video-container iframe"
);
if
(
iframe
)
{
if
rame
.
contentWindow
.
postMessage
(
"resize"
,
"*"
);
}
}
// Event handler for server sent data.
// The callback function is invoked whenever the server emits data
// to the client. The data is then displayed in the "Received"
//
section of the page.
socket
.
on
(
'my_response'
,
function
(
msg
,
cb
)
{
$
(
'#log'
).
append
(
'<br>'
+
$
(
'<div/>'
).
text
(
'Received #'
+
msg
.
count
+
': '
+
msg
.
data
).
html
());
if
(
cb
)
cb
();
});
let
isResizing
=
false
;
// Interval function that tests message latency by sending a "ping"
// message. The server then responds with a "pong" message and the
// round trip time is measured.
var
ping_pong_times
=
[];
var
start_time
;
window
.
setInterval
(
function
()
{
start_time
=
(
new
Date
).
getTime
();
$
(
'#transport'
).
text
(
socket
.
io
.
engine
.
transport
.
name
);
socket
.
emit
(
'my_ping'
);
},
1000
);
// Handler for the "pong" message. When the pong is received, the
// time from the ping is stored, and the average of the last 30
// samples is average and displayed.
socket
.
on
(
'my_pong'
,
function
()
{
var
latency
=
(
new
Date
).
getTime
()
-
start_time
;
ping_pong_times
.
push
(
latency
);
ping_pong_times
=
ping_pong_times
.
slice
(
-
30
);
// keep last 30 samples
var
sum
=
0
;
for
(
var
i
=
0
;
i
<
ping_pong_times
.
length
;
i
++
)
sum
+=
ping_pong_times
[
i
];
$
(
'#ping-pong'
).
text
(
Math
.
round
(
10
*
sum
/
ping_pong_times
.
length
)
/
10
);
});
resizeHandle
.
addEventListener
(
'mousedown'
,
(
e
)
=>
{
isResizing
=
true
;
document
.
addEventListener
(
'mousemove'
,
handleMouseMove
);
document
.
addEventListener
(
'mouseup'
,
stopResize
);
});
window
.
setInterval
(
function
()
{
socket
.
emit
(
'get_queue'
);
},
200
);
function
handleMouseMove
(
e
)
{
if
(
!
isResizing
)
return
;
let
newWidth
=
e
.
clientX
;
// Limit sidebar width between 50px and 50% of screen
newWidth
=
Math
.
max
(
50
,
Math
.
min
(
newWidth
,
containerWidth
/
2
));
adjustSidebarWidth
(
newWidth
);
}
socket
.
on
(
'change_output'
,
function
(
msg
,
cb
)
{
//console.log('CHANGE OUTPUT');
//console.log(msg);
$
(
'.output_'
+
msg
.
button
).
css
(
'background-color'
,
msg
.
color
);
});
function
stopResize
()
{
isResizing
=
false
;
document
.
removeEventListener
(
'mousemove'
,
handleMouseMove
);
document
.
removeEventListener
(
'mouseup'
,
stopResize
);
}
socket
.
on
(
'change_feedback'
,
function
(
msg
,
cb
)
{
if
(
msg
.
hasOwnProperty
(
"color"
))
$
(
'.feedback_'
+
msg
.
feedback
).
css
(
'background-color'
,
msg
.
color
);
if
(
msg
.
hasOwnProperty
(
"title"
))
$
(
'.feedback_'
+
msg
.
feedback
).
text
(
msg
.
title
);
});
// Prevent zoom on double-tap for mobile
document
.
addEventListener
(
'touchmove'
,
function
(
event
)
{
if
(
event
.
scale
!==
1
)
{
event
.
preventDefault
();
}
},
{
passive
:
false
});
});
</script>
</body>
<div
id=
"log"
></div>
<div
id=
"ping-pong"
></div>
ms
</b>
<div
id=
"transport"
></div>
</body>
</html>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment