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
8853586d
Commit
8853586d
authored
8 months ago
by
nextime
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Really revert the changes
parent
0a5b7c4e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
204 additions
and
46 deletions
+204
-46
shmcamstudio
shmcamstudio
+204
-46
No files found.
shmcamstudio
View file @
8853586d
...
@@ -33,15 +33,15 @@ import vlc
...
@@ -33,15 +33,15 @@ import vlc
# Read configuration
# Read configuration
config
=
configparser
.
ConfigParser
()
config
=
configparser
.
ConfigParser
()
config
.
read
(
"config.ini"
)
config
.
read
(
'config.ini'
)
# Setup logging
# Setup logging
log_file
=
config
.
get
(
"General"
,
"log_file"
,
fallback
=
"/tmp/streaming_control.log"
)
log_file
=
config
.
get
(
'General'
,
'log_file'
,
fallback
=
'/tmp/streaming_control.log'
)
log_level
=
config
.
get
(
"General"
,
"log_level"
,
fallback
=
"INFO"
)
log_level
=
config
.
get
(
'General'
,
'log_level'
,
fallback
=
'INFO'
)
logging
.
basicConfig
(
logging
.
basicConfig
(
level
=
getattr
(
logging
,
log_level
),
level
=
getattr
(
logging
,
log_level
),
format
=
"
%(asctime)
s -
%(levelname)
s -
%(message)
s"
,
format
=
'
%(asctime)
s -
%(levelname)
s -
%(message)
s'
,
handlers
=
[
handlers
=
[
RotatingFileHandler
(
log_file
,
maxBytes
=
1024
*
1024
,
backupCount
=
5
),
RotatingFileHandler
(
log_file
,
maxBytes
=
1024
*
1024
,
backupCount
=
5
),
logging
.
StreamHandler
(
sys
.
stdout
)
logging
.
StreamHandler
(
sys
.
stdout
)
...
@@ -53,7 +53,7 @@ logger = logging.getLogger(__name__)
...
@@ -53,7 +53,7 @@ logger = logging.getLogger(__name__)
flask_app
=
Flask
(
__name__
)
flask_app
=
Flask
(
__name__
)
# Command Mapping
# Command Mapping
COMMANDS
=
dict
(
config
[
"Commands"
])
COMMANDS
=
dict
(
config
[
'Commands'
])
def
run_command
(
command
):
def
run_command
(
command
):
try
:
try
:
...
@@ -65,13 +65,13 @@ def run_command(command):
...
@@ -65,13 +65,13 @@ def run_command(command):
logger
.
error
(
f
"Error executing command {command}: {e}"
)
logger
.
error
(
f
"Error executing command {command}: {e}"
)
return
f
"Error: {e}"
return
f
"Error: {e}"
@
flask_app
.
route
(
"/"
)
@
flask_app
.
route
(
'/'
)
def
index
():
def
index
():
return
render_template
(
"index.html"
,
commands
=
COMMANDS
)
return
render_template
(
'index.html'
,
commands
=
COMMANDS
)
@
flask_app
.
route
(
"/execute"
,
methods
=
[
"POST"
])
@
flask_app
.
route
(
'/execute'
,
methods
=
[
'POST'
])
def
execute
():
def
execute
():
command_key
=
request
.
form
.
get
(
"command"
)
command_key
=
request
.
form
.
get
(
'command'
)
if
command_key
in
COMMANDS
:
if
command_key
in
COMMANDS
:
result
=
run_command
(
COMMANDS
[
command_key
])
result
=
run_command
(
COMMANDS
[
command_key
])
...
@@ -79,13 +79,13 @@ def execute():
...
@@ -79,13 +79,13 @@ def execute():
else
:
else
:
return
"Invalid command"
,
400
return
"Invalid command"
,
400
@
flask_app
.
route
(
"/stream"
)
@
flask_app
.
route
(
'/stream'
)
def
stream
():
def
stream
():
stream_url
=
config
.
get
(
"Web"
,
"stream_url"
,
fallback
=
"https://192.168.42.1/HLS/record/Live.m3u8"
)
stream_url
=
config
.
get
(
'Web'
,
'stream_url'
,
fallback
=
"https://192.168.42.1/HLS/record/Live.m3u8"
)
return
render_template
(
"stream.html"
,
stream_url
=
stream_url
)
return
render_template
(
'stream.html'
,
stream_url
=
stream_url
)
def
create_daemon
():
def
create_daemon
():
if
os
.
name
==
"posix"
:
# Unix-like systems
if
os
.
name
==
'posix'
:
# Unix-like systems
try
:
try
:
# First fork
# First fork
pid
=
os
.
fork
()
pid
=
os
.
fork
()
...
@@ -93,11 +93,11 @@ def create_daemon():
...
@@ -93,11 +93,11 @@ def create_daemon():
# Exit first parent
# Exit first parent
sys
.
exit
(
0
)
sys
.
exit
(
0
)
except
OSError
as
err
:
except
OSError
as
err
:
logger
.
error
(
f
"Fork #1 failed: {err}"
)
logger
.
error
(
f
'Fork #1 failed: {err}'
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
# Decouple from parent environment
# Decouple from parent environment
os
.
chdir
(
"/"
)
os
.
chdir
(
'/'
)
os
.
setsid
()
os
.
setsid
()
os
.
umask
(
0
)
os
.
umask
(
0
)
...
@@ -108,53 +108,211 @@ def create_daemon():
...
@@ -108,53 +108,211 @@ def create_daemon():
# Exit from second parent
# Exit from second parent
sys
.
exit
(
0
)
sys
.
exit
(
0
)
except
OSError
as
err
:
except
OSError
as
err
:
logger
.
error
(
f
"Fork #2 failed: {err}"
)
logger
.
error
(
f
'Fork #2 failed: {err}'
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
# Redirect standard file descriptors
# Redirect standard file descriptors
sys
.
stdout
.
flush
()
sys
.
stdout
.
flush
()
sys
.
stderr
.
flush
()
sys
.
stderr
.
flush
()
si
=
open
(
os
.
devnull
,
"r"
)
si
=
open
(
os
.
devnull
,
'r'
)
so
=
open
(
os
.
devnull
,
"a+"
)
so
=
open
(
os
.
devnull
,
'a+'
)
se
=
open
(
os
.
devnull
,
"a+"
)
se
=
open
(
os
.
devnull
,
'a+'
)
os
.
dup2
(
si
.
fileno
(),
sys
.
stdin
.
fileno
())
os
.
dup2
(
si
.
fileno
(),
sys
.
stdin
.
fileno
())
os
.
dup2
(
so
.
fileno
(),
sys
.
stdout
.
fileno
())
os
.
dup2
(
so
.
fileno
(),
sys
.
stdout
.
fileno
())
os
.
dup2
(
se
.
fileno
(),
sys
.
stderr
.
fileno
())
os
.
dup2
(
se
.
fileno
(),
sys
.
stderr
.
fileno
())
elif
os
.
name
==
'nt'
:
# Windows
try
:
# Hide the console window
si
=
subprocess
.
STARTUPINFO
()
si
.
dwFlags
|=
subprocess
.
STARTF_USESHOWWINDOW
# Start the script as a new process
subprocess
.
Popen
([
sys
.
executable
,
__file__
],
startupinfo
=
si
,
creationflags
=
subprocess
.
CREATE_NEW_PROCESS_GROUP
)
# Exit the current process
sys
.
exit
(
0
)
except
Exception
as
err
:
logger
.
error
(
f
'Failed to create background process: {err}'
)
sys
.
exit
(
1
)
else
:
logger
.
error
(
f
'Unsupported operating system: {os.name}'
)
sys
.
exit
(
1
)
def
check_port_available
(
port
):
"""Check if a port is available"""
with
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
as
s
:
return
s
.
connect_ex
((
'localhost'
,
port
))
!=
0
def
run_flask_app
(
port
=
5000
,
daemon_mode
=
False
):
"""Run Flask app with optional daemon mode"""
if
not
check_port_available
(
port
):
logger
.
error
(
f
"Port {port} is already in use"
)
sys
.
exit
(
1
)
logger
.
info
(
f
"Starting Flask app on port {port}"
)
if
daemon_mode
and
sys
.
platform
!=
'win32'
:
create_daemon
()
flask_app
.
run
(
host
=
'0.0.0.0'
,
port
=
port
,
debug
=
False
,
use_reloader
=
False
)
class
VideoPlayer
:
def
__init__
(
self
,
master
,
video_url
):
self
.
master
=
master
# VLC player setup
args
=
[]
_isLinux
=
sys
.
platform
.
startswith
(
'linux'
)
if
_isLinux
:
args
.
append
(
'--vout=mmal_vout'
)
# Create a VLC instance
self
.
Instance
=
vlc
.
Instance
(
args
)
# Create a new MediaPlayer
self
.
player
=
self
.
Instance
.
media_player_new
()
# Set the media
media
=
self
.
Instance
.
media_new
(
video_url
)
self
.
player
.
set_media
(
media
)
# Create a frame for the video
self
.
video_frame
=
self
.
master
self
.
video_frame
.
pack
(
fill
=
tk
.
BOTH
,
expand
=
True
)
self
.
canvas
=
tk
.
Canvas
(
self
.
video_frame
,
width
=
800
)
self
.
canvas
.
pack
(
fill
=
tk
.
BOTH
,
expand
=
True
)
def
create_tkinter_interface
():
# Embed the VLC Video
root
=
tk
.
Tk
()
win_id
=
self
.
canvas
.
winfo_id
()
root
.
title
(
config
.
get
(
"Tkinter"
,
"window_title"
,
fallback
=
"SHM Cam Studio"
))
if
_isLinux
:
root
.
geometry
(
f
"{config.get(Tkinter, window_width, fallback=300)}x{config.get(Tkinter, window_height, fallback=400)}"
)
self
.
player
.
set_xwindow
(
win_id
)
else
:
self
.
player
.
set_hwnd
(
win_id
)
# Play the video
self
.
player
.
play
()
button_font
=
tkFont
.
Font
(
size
=
int
(
config
.
get
(
"Tkinter"
,
"font_size"
,
fallback
=
"12"
)))
button_width
=
int
(
config
.
get
(
"Tkinter"
,
"button_width"
,
fallback
=
"20"
))
button_height
=
int
(
config
.
get
(
"Tkinter"
,
"button_height"
,
fallback
=
"2"
))
for
command_name
,
command
in
COMMANDS
.
items
():
button
=
tk
.
Button
(
root
,
text
=
command_name
,
command
=
lambda
cmd
=
command
:
run_command
(
cmd
),
font
=
button_font
,
width
=
button_width
,
height
=
button_height
)
button
.
pack
(
pady
=
5
)
root
.
mainloop
()
def
create_tkinter_gui
():
# Create the main window
window
=
tk
.
Tk
()
window
.
title
(
"Streaming Control Panel"
)
def
run_flask
():
helv36
=
tkFont
.
Font
(
family
=
'Helvetica'
,
size
=
13
,
weight
=
'bold'
)
port
=
config
.
get
(
"Web"
,
"port"
,
fallback
=
"5000"
)
flask_app
.
run
(
host
=
"0.0.0.0"
,
port
=
int
(
port
))
if
__name__
==
"__main__"
:
# Frame for the left side
parser
=
argparse
.
ArgumentParser
(
description
=
"SHM Cam Studio"
)
fleft
=
tk
.
Frame
(
window
)
parser
.
add_argument
(
"--daemon"
,
action
=
"store_true"
,
help
=
"Run as daemon"
)
fleft
.
pack
(
side
=
tk
.
LEFT
,
fill
=
tk
.
BOTH
,
expand
=
True
)
args
=
parser
.
parse_args
()
if
args
.
daemon
:
# URL of your HLS stream
create_daemon
()
video_url
=
"rtmp://192.168.42.1/record/Live"
VideoPlayer
(
fleft
,
video_url
)
# Frame for the right side
fright
=
tk
.
Frame
(
window
)
fright
.
pack
(
side
=
tk
.
RIGHT
,
fill
=
tk
.
BOTH
,
expand
=
True
)
flask_thread
=
threading
.
Thread
(
target
=
run_flask
)
# Frame for the first two rows in the right frame
flask_thread
.
start
()
frame1
=
tk
.
Frame
(
fright
)
frame1
.
pack
(
fill
=
tk
.
BOTH
,
expand
=
True
)
# Buttons configuration
buttons_row0
=
[
(
'PRIVATE STEFY'
,
'smblur_private_stefy'
),
(
'PRIVATE LEELOO'
,
'smblur_private_leeloo'
),
(
'PRIVATE JASMIN'
,
'smblur_private_jasmin'
),
(
'PRIVATE OTHER'
,
'smblur_private'
)
]
buttons_row1
=
[
(
'OPEN/CLOSE STEFY'
,
'smblur_stefy'
),
(
'OPEN/CLOSE LEELOO'
,
'smblur_leeloo'
),
(
'OPEN/CLOSE JASMIN'
,
'smblur_jasmin'
),
(
'OPEN/CLOSE OTHERS'
,
'smblur_shine'
)
]
# Create buttons for the first two rows
for
j
,
(
text
,
command
)
in
enumerate
(
buttons_row0
):
button
=
tk
.
Button
(
frame1
,
text
=
text
,
font
=
helv36
,
width
=
25
,
height
=
15
,
bg
=
"green"
,
fg
=
"white"
,
command
=
lambda
cmd
=
command
:
run_command
(
cmd
))
button
.
grid
(
row
=
0
,
column
=
j
,
sticky
=
'nsew'
)
for
j
,
(
text
,
command
)
in
enumerate
(
buttons_row1
):
button
=
tk
.
Button
(
frame1
,
text
=
text
,
font
=
helv36
,
width
=
25
,
height
=
15
,
bg
=
"green"
,
fg
=
"white"
,
command
=
lambda
cmd
=
command
:
run_command
(
cmd
))
button
.
grid
(
row
=
1
,
column
=
j
,
sticky
=
'nsew'
)
# Configure the columns in the first frame
for
i
in
range
(
4
):
frame1
.
grid_columnconfigure
(
i
,
weight
=
1
)
# Frame for the third row in the right frame
frame2
=
tk
.
Frame
(
fright
)
frame2
.
pack
(
fill
=
tk
.
BOTH
,
expand
=
True
)
# Row 2 with 3 buttons
buttons_row2
=
[
(
'TEASE'
,
'smblur_tease'
),
(
'TEASE ALL'
,
'smblur_teaseall'
),
(
'OPEN'
,
'smblur_clean'
)
]
# Create buttons for the third row
for
j
,
(
text
,
command
)
in
enumerate
(
buttons_row2
):
button
=
tk
.
Button
(
frame2
,
text
=
text
,
font
=
helv36
,
width
=
30
,
height
=
25
,
bg
=
"blue"
,
fg
=
"white"
,
command
=
lambda
cmd
=
command
:
run_command
(
cmd
))
button
.
grid
(
row
=
0
,
column
=
j
,
sticky
=
'nsew'
)
# Configure the columns in the second frame
for
i
in
range
(
3
):
frame2
.
grid_columnconfigure
(
i
,
weight
=
1
)
# Add a button to open web interface
web_button
=
tk
.
Button
(
frame2
,
text
=
"Open Web Interface"
,
command
=
lambda
:
webbrowser
.
open
(
'http://localhost:5000'
),
bg
=
"purple"
,
fg
=
"white"
,
font
=
helv36
)
web_button
.
grid
(
row
=
1
,
column
=
1
,
sticky
=
'nsew'
)
return
window
def
main
():
# Setup argument parser
parser
=
argparse
.
ArgumentParser
(
description
=
'Streaming Control Panel'
)
parser
.
add_argument
(
'--web-only'
,
action
=
'store_true'
,
help
=
'Start only the web interface'
)
parser
.
add_argument
(
'--daemon'
,
action
=
'store_true'
,
help
=
'Run in daemon mode (Unix-like systems only)'
)
parser
.
add_argument
(
'--port'
,
type
=
int
,
default
=
5000
,
help
=
'Port for the web interface (default: 5000)'
)
# Parse arguments
args
=
parser
.
parse_args
()
try
:
# Daemon mode for web interface
if
args
.
web_only
or
args
.
daemon
:
run_flask_app
(
port
=
args
.
port
,
daemon_mode
=
args
.
daemon
)
else
:
# Start web interface in a background thread
web_thread
=
threading
.
Thread
(
target
=
run_flask_app
,
kwargs
=
{
'port'
:
args
.
port
},
daemon
=
True
)
web_thread
.
start
()
create_tkinter_interface
()
# Launch Tkinter GUI
window
=
create_tkinter_gui
()
window
.
mainloop
()
# Cleanup
except
Exception
as
e
:
flask_thread
.
join
()
logger
.
error
(
f
"Unexpected error: {e}"
)
sys
.
exit
(
1
)
if
__name__
==
'__main__'
:
main
()
This diff is collapsed.
Click to expand it.
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