Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
MBetterc
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
0
Merge Requests
0
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
Mbetter
MBetterc
Commits
4b0a8e87
Commit
4b0a8e87
authored
Jan 23, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First adaptation for mobile API client
parent
dc928a1f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
143 additions
and
9 deletions
+143
-9
main.py
main.py
+39
-3
settings.py
mbetterclient/config/settings.py
+4
-1
application.py
mbetterclient/core/application.py
+45
-5
test_headless_streaming.py
test_headless_streaming.py
+55
-0
No files found.
main.py
View file @
4b0a8e87
...
...
@@ -166,6 +166,12 @@ Examples:
action
=
'store_true'
,
help
=
'Disable PyQt interface (web dashboard only)'
)
parser
.
add_argument
(
'--headless'
,
action
=
'store_true'
,
help
=
'Run in headless mode with HLS streaming (alias for --no-qt)'
)
parser
.
add_argument
(
'--no-web'
,
...
...
@@ -229,6 +235,19 @@ Examples:
help
=
'Enable single window overlay mode (overlay stacks on top of player widget instead of separate window)'
)
parser
.
add_argument
(
'--streamer-port'
,
type
=
int
,
default
=
5884
,
help
=
'Port for HLS video streaming server (default: 5884)'
)
parser
.
add_argument
(
'--test-stream'
,
action
=
'store_true'
,
help
=
'Enable test mode for headless streaming (automatically starts INTRO video)'
)
return
parser
.
parse_args
()
def
validate_arguments
(
args
):
...
...
@@ -236,11 +255,19 @@ def validate_arguments(args):
if
args
.
no_qt
and
args
.
no_web
:
print
(
"Error: Cannot disable both Qt and web interfaces"
)
sys
.
exit
(
1
)
if
args
.
no_qt
and
args
.
headless
:
print
(
"Error: Cannot use both --no-qt and --headless (they are aliases)"
)
sys
.
exit
(
1
)
if
args
.
web_port
<
1
or
args
.
web_port
>
65535
:
print
(
"Error: Web port must be between 1 and 65535"
)
sys
.
exit
(
1
)
if
args
.
streamer_port
<
1
or
args
.
streamer_port
>
65535
:
print
(
"Error: Streamer port must be between 1 and 65535"
)
sys
.
exit
(
1
)
# Directory creation is handled by AppSettings.ensure_directories()
# which uses persistent user directories for PyInstaller compatibility
pass
...
...
@@ -269,12 +296,14 @@ def main():
settings
.
fullscreen
=
not
args
.
no_fullscreen
settings
.
web_host
=
args
.
web_host
settings
.
web_port
=
args
.
web_port
settings
.
streamer_port
=
args
.
streamer_port
settings
.
debug_mode
=
args
.
debug
or
args
.
dev_mode
settings
.
dev_message
=
args
.
dev_message
settings
.
debug_messages
=
args
.
debug_messages
settings
.
debug_player
=
args
.
debug_player
settings
.
debug_overlay
=
args
.
debug_overlay
settings
.
enable_qt
=
not
args
.
no_qt
settings
.
enable_qt
=
not
args
.
no_qt
and
not
args
.
headless
settings
.
enable_headless
=
args
.
headless
settings
.
enable_web
=
not
args
.
no_web
# Timer settings
...
...
@@ -300,6 +329,13 @@ def main():
# Overlay settings
settings
.
qt
.
overlay_single_window
=
args
.
overlay_single
# Test streaming settings
# Enable test stream automatically in headless mode
settings
.
test_stream
=
args
.
test_stream
or
args
.
headless
# Set headless flag
settings
.
enable_headless
=
args
.
headless
if
args
.
db_path
:
settings
.
database_path
=
args
.
db_path
...
...
mbetterclient/config/settings.py
View file @
4b0a8e87
...
...
@@ -374,6 +374,7 @@ class AppSettings:
debug_overlay
:
bool
=
False
# Enable debug mode for overlay rendering
enable_web
:
bool
=
True
enable_qt
:
bool
=
True
enable_headless
:
bool
=
False
enable_api_client
:
bool
=
True
enable_screen_cast
:
bool
=
True
# Enabled by default, can be disabled with --no-screen-cast
...
...
@@ -381,6 +382,7 @@ class AppSettings:
fullscreen
:
bool
=
True
web_host
:
str
=
"127.0.0.1"
web_port
:
int
=
5001
streamer_port
:
int
=
5884
# HLS streaming port
database_path
:
Optional
[
str
]
=
None
def
__post_init__
(
self
):
...
...
@@ -421,6 +423,7 @@ class AppSettings:
"debug_overlay"
:
self
.
debug_overlay
,
"enable_web"
:
self
.
enable_web
,
"enable_qt"
:
self
.
enable_qt
,
"enable_headless"
:
self
.
enable_headless
,
"enable_api_client"
:
self
.
enable_api_client
,
"enable_screen_cast"
:
self
.
enable_screen_cast
}
...
...
@@ -452,7 +455,7 @@ class AppSettings:
settings
.
timer
=
TimerConfig
(
**
data
[
"timer"
])
# Update app settings
for
key
in
[
"version"
,
"debug_mode"
,
"dev_message"
,
"debug_messages"
,
"debug_player"
,
"debug_overlay"
,
"enable_web"
,
"enable_qt"
,
"enable_api_client"
,
"enable_screen_cast"
]:
for
key
in
[
"version"
,
"debug_mode"
,
"dev_message"
,
"debug_messages"
,
"debug_player"
,
"debug_overlay"
,
"enable_web"
,
"enable_qt"
,
"enable_
headless"
,
"enable_
api_client"
,
"enable_screen_cast"
]:
if
key
in
data
:
setattr
(
settings
,
key
,
data
[
key
])
...
...
mbetterclient/core/application.py
View file @
4b0a8e87
...
...
@@ -128,10 +128,15 @@ class MbetterClientApplication:
stored_settings
.
fullscreen
=
self
.
settings
.
fullscreen
stored_settings
.
web_host
=
self
.
settings
.
web_host
stored_settings
.
web_port
=
self
.
settings
.
web_port
stored_settings
.
streamer_port
=
getattr
(
self
.
settings
,
'streamer_port'
,
5884
)
# Preserve streamer port
stored_settings
.
database_path
=
self
.
settings
.
database_path
stored_settings
.
enable_qt
=
self
.
settings
.
enable_qt
stored_settings
.
enable_web
=
self
.
settings
.
enable_web
stored_settings
.
enable_screen_cast
=
self
.
settings
.
enable_screen_cast
# Preserve screen cast setting
# Preserve test_stream setting
if
hasattr
(
self
.
settings
,
'test_stream'
):
stored_settings
.
test_stream
=
self
.
settings
.
test_stream
# Preserve command line debug settings
...
...
@@ -147,6 +152,9 @@ class MbetterClientApplication:
stored_settings
.
web
.
ssl_key_path
=
self
.
settings
.
web
.
ssl_key_path
stored_settings
.
web
.
ssl_auto_generate
=
self
.
settings
.
web
.
ssl_auto_generate
# Preserve command line headless setting
stored_settings
.
enable_headless
=
self
.
settings
.
enable_headless
self
.
settings
=
stored_settings
# Restore command-line rustdesk_id after settings merge
...
...
@@ -216,13 +224,19 @@ class MbetterClientApplication:
logger
.
error
(
"Template watcher initialization failed"
)
return
False
# Initialize PyQt video player
# Initialize PyQt video player
or headless RTSP streamer
if
self
.
settings
.
enable_qt
:
if
self
.
_initialize_qt_player
():
components_initialized
+=
1
else
:
logger
.
error
(
"Qt player initialization failed"
)
return
False
elif
self
.
settings
.
enable_headless
:
if
self
.
_initialize_headless_player
():
components_initialized
+=
1
else
:
logger
.
error
(
"Headless player initialization failed"
)
return
False
# Initialize web dashboard
if
self
.
settings
.
enable_web
:
...
...
@@ -326,24 +340,50 @@ class MbetterClientApplication:
"""Initialize PyQt video player"""
try
:
from
..qt_player.player
import
QtVideoPlayer
self
.
qt_player
=
QtVideoPlayer
(
message_bus
=
self
.
message_bus
,
settings
=
self
.
settings
.
qt
,
debug_player
=
self
.
settings
.
debug_player
,
debug_overlay
=
self
.
settings
.
debug_overlay
)
# Don't register with thread manager since QtPlayer no longer inherits from ThreadedComponent
# Instead, we'll handle it separately in the run method
pass
logger
.
info
(
"Qt player initialized"
)
return
True
except
Exception
as
e
:
logger
.
error
(
f
"Qt player initialization failed: {e}"
)
return
False
def
_initialize_headless_player
(
self
)
->
bool
:
"""Initialize headless RTSP streamer"""
try
:
from
..core.rtsp_streamer
import
RTSPStreamer
# Check if test mode is enabled (passed from command line)
test_mode
=
getattr
(
self
.
settings
,
'test_stream'
,
False
)
logger
.
info
(
f
"Application: test_mode from settings: {test_mode}"
)
self
.
headless_player
=
RTSPStreamer
(
message_bus
=
self
.
message_bus
,
settings
=
self
.
settings
,
debug_player
=
self
.
settings
.
debug_player
,
test_mode
=
test_mode
)
# Register with thread manager
self
.
thread_manager
.
register_component
(
"headless_player"
,
self
.
headless_player
)
logger
.
info
(
"Headless RTSP streamer initialized"
)
return
True
except
Exception
as
e
:
logger
.
error
(
f
"Headless player initialization failed: {e}"
)
return
False
def
_initialize_web_dashboard
(
self
)
->
bool
:
"""Initialize web dashboard"""
...
...
test_headless_streaming.py
0 → 100644
View file @
4b0a8e87
#!/usr/bin/env python3
"""
Test script for headless RTSP/HLS streaming
"""
import
sys
import
time
import
os
from
pathlib
import
Path
# Add the project root to Python path
project_root
=
Path
(
__file__
)
.
parent
sys
.
path
.
insert
(
0
,
str
(
project_root
))
from
mbetterclient.core.message_bus
import
MessageBus
,
Message
,
MessageType
,
MessageBuilder
def
test_headless_streaming
():
"""Test headless streaming by sending video play messages"""
# Create message bus
message_bus
=
MessageBus
()
# Register test component
message_bus
.
register_component
(
"test"
)
print
(
"Starting headless streaming test..."
)
# Send a video play message for the INTRO video
intro_path
=
project_root
/
"assets"
/
"INTRO.mp4"
if
not
intro_path
.
exists
():
print
(
f
"INTRO.mp4 not found at {intro_path}"
)
return
print
(
f
"Playing video: {intro_path}"
)
# Create video play message
video_play_message
=
MessageBuilder
.
video_play
(
sender
=
"test"
,
file_path
=
str
(
intro_path
),
overlay_data
=
{
"title"
:
"Test Stream"
,
"message"
:
"Headless streaming test"
}
)
# Publish the message
message_bus
.
publish
(
video_play_message
,
broadcast
=
True
)
print
(
"Video play message sent. Streaming should start..."
)
# Wait a bit
time
.
sleep
(
5
)
print
(
"Test completed. Check if streaming is working."
)
if
__name__
==
"__main__"
:
test_headless_streaming
()
\ No newline at end of file
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