♻️ refactor(launcher/plugins/screencapture): use screen-capture.sh script for screenshot and screen recording functionality

This commit is contained in:
sankalp committed 2025-06-19 14:06:57 +05:45
1 parent e257ec2a2b
commit d6dee7c50d
1 file changed
+306 -34
+306 -34
View File
@@ -1,26 +1,28 @@
""" """
Screencapture plugin for the launcher. Screencapture plugin for the launcher.
Provides screenshot and screen recording functionality. Provides screenshot and screen recording functionality using screen-capture.sh script.
""" """
import os
import subprocess
from typing import List from typing import List
from modules.launcher.plugin_base import PluginBase from modules.launcher.plugin_base import PluginBase
from modules.launcher.result import Result from modules.launcher.result import Result
from services.screencapture import ScreenCapture
from utils.icons import screenrecord, screenshots, ssfull, ssregion, stop from utils.icons import screenrecord, screenshots, ssfull, ssregion, stop
class ScreencapturePlugin(PluginBase): class ScreencapturePlugin(PluginBase):
""" """
Plugin for taking screenshots and screen recordings. Plugin for taking screenshots and screen recordings using screen-capture.sh script.
""" """
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.display_name = "Screencapture" self.display_name = "Screencapture"
self.description = "Take screenshots and screen recordings" self.description = "Take screenshots and screen recordings"
self.screencapture = ScreenCapture() # Path to the screen-capture script
self.script_path = os.path.expanduser("~/Modus/scripts/screen-capture.sh")
def initialize(self): def initialize(self):
"""Initialize the screencapture plugin.""" """Initialize the screencapture plugin."""
@@ -30,35 +32,191 @@ class ScreencapturePlugin(PluginBase):
"""Cleanup the screencapture plugin.""" """Cleanup the screencapture plugin."""
pass pass
def get_commands(self):
"""Return available commands for this plugin."""
return {
# Screenshot commands
"screenshot": "Take a screenshot of the main display",
"ss": "Take a screenshot of the main display",
"screenshot-region": "Take a screenshot of selected region",
"ss-region": "Take a screenshot of selected region",
"screenshot-both": "Take a screenshot of both displays",
"ss-both": "Take a screenshot of both displays",
"screenshot-hdmi": "Take a screenshot of HDMI display",
"ss-hdmi": "Take a screenshot of HDMI display",
# Recording commands (with audio)
"record": "Start recording main display with audio",
"rec": "Start recording main display with audio",
"record-region": "Start recording selected region with audio",
"rec-region": "Start recording selected region with audio",
"record-hdmi": "Start recording HDMI display with audio",
"rec-hdmi": "Start recording HDMI display with audio",
# Recording commands (no audio)
"record-noaudio": "Start recording main display without audio",
"rec-noaudio": "Start recording main display without audio",
"record-noaudio-region": "Start recording selected region without audio",
"rec-noaudio-region": "Start recording selected region without audio",
"record-noaudio-hdmi": "Start recording HDMI display without audio",
"rec-noaudio-hdmi": "Start recording HDMI display without audio",
# High-quality recording commands
"record-hq": "Start high-quality recording of main display",
"rec-hq": "Start high-quality recording of main display",
"record-hq-region": "Start high-quality recording of selected region",
"rec-hq-region": "Start high-quality recording of selected region",
"record-hq-hdmi": "Start high-quality recording of HDMI display",
"rec-hq-hdmi": "Start high-quality recording of HDMI display",
# GIF recording commands
"record-gif": "Start GIF recording of main display",
"rec-gif": "Start GIF recording of main display",
"record-gif-region": "Start GIF recording of selected region",
"rec-gif-region": "Start GIF recording of selected region",
# Control commands
"stop": "Stop current recording",
# Conversion commands
"convert-webm": "Convert recordings to WebM format",
"conv-webm": "Convert recordings to WebM format",
"convert-iphone": "Convert recordings for iPhone compatibility",
"conv-iphone": "Convert recordings for iPhone compatibility",
"convert-youtube": "Convert recordings for YouTube upload",
"conv-youtube": "Convert recordings for YouTube upload",
"convert-gif": "Convert recordings to GIF format",
"conv-gif": "Convert recordings to GIF format",
}
def _run_script(self, *args):
"""Execute the screen-capture script with given arguments."""
try:
subprocess.Popen([self.script_path] + list(args))
except Exception as e:
print(f"Error running screen-capture script: {e}")
def _is_recording(self):
"""Check if recording is currently active."""
try:
result = subprocess.run(
[self.script_path, "status"],
capture_output=True,
text=True
)
return result.stdout.strip() == "true"
except Exception:
return False
def _get_command_result(self, command: str) -> Result:
"""Get a Result object for a specific command."""
# Import here to avoid circular imports
from utils.icons import ssfull, ssregion, screenshots, screenrecord, stop
command_info = {
# Screenshot commands
"screenshot": ("Take Screenshot (eDP-1)", "Capture the main display", ssfull, lambda: self._run_script("screenshot", "eDP-1")),
"ss": ("Take Screenshot (eDP-1)", "Capture the main display", ssfull, lambda: self._run_script("screenshot", "eDP-1")),
"screenshot-region": ("Take Region Screenshot", "Capture a selected region", ssregion, lambda: self._run_script("screenshot", "selection")),
"ss-region": ("Take Region Screenshot", "Capture a selected region", ssregion, lambda: self._run_script("screenshot", "selection")),
"screenshot-both": ("Take Screenshot (Both Displays)", "Capture both displays combined", screenshots, lambda: self._run_script("screenshot", "both")),
"ss-both": ("Take Screenshot (Both Displays)", "Capture both displays combined", screenshots, lambda: self._run_script("screenshot", "both")),
"screenshot-hdmi": ("Take Screenshot (HDMI-A-1)", "Capture HDMI display", ssfull, lambda: self._run_script("screenshot", "HDMI-A-1")),
"ss-hdmi": ("Take Screenshot (HDMI-A-1)", "Capture HDMI display", ssfull, lambda: self._run_script("screenshot", "HDMI-A-1")),
# Recording commands (with audio)
"record": ("Start Recording (eDP-1)", "Record the main display with audio", screenrecord, lambda: self._run_script("record", "eDP-1")),
"rec": ("Start Recording (eDP-1)", "Record the main display with audio", screenrecord, lambda: self._run_script("record", "eDP-1")),
"record-region": ("Start Region Recording", "Record a selected region with audio", screenrecord, lambda: self._run_script("record", "selection")),
"rec-region": ("Start Region Recording", "Record a selected region with audio", screenrecord, lambda: self._run_script("record", "selection")),
"record-hdmi": ("Start Recording (HDMI-A-1)", "Record HDMI display with audio", screenrecord, lambda: self._run_script("record", "HDMI-A-1")),
"rec-hdmi": ("Start Recording (HDMI-A-1)", "Record HDMI display with audio", screenrecord, lambda: self._run_script("record", "HDMI-A-1")),
# Recording commands (no audio)
"record-noaudio": ("Start Recording No Audio (eDP-1)", "Record the main display without audio", screenrecord, lambda: self._run_script("record-noaudio", "eDP-1")),
"rec-noaudio": ("Start Recording No Audio (eDP-1)", "Record the main display without audio", screenrecord, lambda: self._run_script("record-noaudio", "eDP-1")),
"record-noaudio-region": ("Start Region Recording No Audio", "Record a selected region without audio", screenrecord, lambda: self._run_script("record-noaudio", "selection")),
"rec-noaudio-region": ("Start Region Recording No Audio", "Record a selected region without audio", screenrecord, lambda: self._run_script("record-noaudio", "selection")),
"record-noaudio-hdmi": ("Start Recording No Audio (HDMI-A-1)", "Record HDMI display without audio", screenrecord, lambda: self._run_script("record-noaudio", "HDMI-A-1")),
"rec-noaudio-hdmi": ("Start Recording No Audio (HDMI-A-1)", "Record HDMI display without audio", screenrecord, lambda: self._run_script("record-noaudio", "HDMI-A-1")),
# High-quality recording commands
"record-hq": ("Start HQ Recording (eDP-1)", "High-quality recording for YouTube", screenrecord, lambda: self._run_script("record-hq", "eDP-1")),
"rec-hq": ("Start HQ Recording (eDP-1)", "High-quality recording for YouTube", screenrecord, lambda: self._run_script("record-hq", "eDP-1")),
"record-hq-region": ("Start HQ Region Recording", "High-quality region recording", screenrecord, lambda: self._run_script("record-hq", "selection")),
"rec-hq-region": ("Start HQ Region Recording", "High-quality region recording", screenrecord, lambda: self._run_script("record-hq", "selection")),
"record-hq-hdmi": ("Start HQ Recording (HDMI-A-1)", "High-quality HDMI recording", screenrecord, lambda: self._run_script("record-hq", "HDMI-A-1")),
"rec-hq-hdmi": ("Start HQ Recording (HDMI-A-1)", "High-quality HDMI recording", screenrecord, lambda: self._run_script("record-hq", "HDMI-A-1")),
# GIF recording commands
"record-gif": ("Start GIF Recording (eDP-1)", "Record as optimized GIF", screenrecord, lambda: self._run_script("record-gif", "eDP-1")),
"rec-gif": ("Start GIF Recording (eDP-1)", "Record as optimized GIF", screenrecord, lambda: self._run_script("record-gif", "eDP-1")),
"record-gif-region": ("Start GIF Region Recording", "Record selected region as GIF", screenrecord, lambda: self._run_script("record-gif", "selection")),
"rec-gif-region": ("Start GIF Region Recording", "Record selected region as GIF", screenrecord, lambda: self._run_script("record-gif", "selection")),
# Control commands
"stop": ("Stop Recording", "Stop the current screen recording", stop, lambda: self._run_script("record", "stop")),
# Conversion commands
"convert-webm": ("Convert to WebM", "Convert MKV recordings to WebM format", screenrecord, lambda: self._run_script("convert", "webm")),
"conv-webm": ("Convert to WebM", "Convert MKV recordings to WebM format", screenrecord, lambda: self._run_script("convert", "webm")),
"convert-iphone": ("Convert for iPhone", "Convert recordings for iPhone compatibility", screenrecord, lambda: self._run_script("convert", "iphone")),
"conv-iphone": ("Convert for iPhone", "Convert recordings for iPhone compatibility", screenrecord, lambda: self._run_script("convert", "iphone")),
"convert-youtube": ("Convert for YouTube", "Convert recordings for YouTube upload", screenrecord, lambda: self._run_script("convert", "youtube")),
"conv-youtube": ("Convert for YouTube", "Convert recordings for YouTube upload", screenrecord, lambda: self._run_script("convert", "youtube")),
"convert-gif": ("Convert to GIF", "Convert video recordings to GIF", screenrecord, lambda: self._run_script("convert", "gif")),
"conv-gif": ("Convert to GIF", "Convert video recordings to GIF", screenrecord, lambda: self._run_script("convert", "gif")),
}
if command in command_info:
title, subtitle, icon, action = command_info[command]
return Result(
title=title,
subtitle=subtitle,
icon_markup=icon,
action=action,
relevance=1.0,
plugin_name=self.display_name,
)
return None
def query(self, query_string: str) -> List[Result]: def query(self, query_string: str) -> List[Result]:
"""Search for screencapture actions based on query.""" """Search for screencapture actions based on query."""
# Remove the trigger word from the query # Clean the query string
query = query_string.replace("screencapture", "").strip().lower() query = query_string.strip().lower()
results = [] results = []
# If recording is active, show stop button first # Check if query matches a command and return it as a result
if self.screencapture.is_recording: command_result = self._get_command_result(query)
if command_result:
return [command_result]
# Check recording status
is_recording = self._is_recording()
# If recording is active, show stop button first with highest relevance
if is_recording:
results.append( results.append(
Result( Result(
title="Stop Recording", title="Stop Recording",
subtitle="Stop the current screen recording", subtitle="Stop the current screen recording",
icon_markup=stop, icon_markup=stop,
action=self.screencapture.screencast_stop, action=lambda: self._run_script("record", "stop"),
relevance=1.0, relevance=2.0, # Highest relevance to appear at top
plugin_name=self.display_name, plugin_name=self.display_name,
) )
) )
return results
# Screenshot actions # Screenshot actions
results.extend( results.extend(
[ [
Result( Result(
title="Take Screenshot", title="Take Screenshot",
subtitle="Capture the entire screen", subtitle="Capture the entire screen (eDP-1)",
icon_markup=ssfull, icon_markup=ssfull,
action=lambda: self.screencapture.screenshot(fullscreen=True), action=lambda: self._run_script("screenshot", "eDP-1"),
relevance=1.0, relevance=1.0,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
@@ -66,29 +224,37 @@ class ScreencapturePlugin(PluginBase):
title="Take Region Screenshot", title="Take Region Screenshot",
subtitle="Capture a selected region", subtitle="Capture a selected region",
icon_markup=ssregion, icon_markup=ssregion,
action=lambda: self.screencapture.screenshot(fullscreen=False), action=lambda: self._run_script("screenshot", "selection"),
relevance=0.9, relevance=0.9,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
Result( Result(
title="Take Screenshot (Clipboard Only)", title="Take Screenshot (Both Displays)",
subtitle="Capture and copy to clipboard", subtitle="Capture both displays combined",
icon_markup=screenshots, icon_markup=screenshots,
action=lambda: self.screencapture.screenshot(save_copy=False), action=lambda: self._run_script("screenshot", "both"),
relevance=0.8, relevance=0.8,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
Result(
title="Take Screenshot (HDMI-A-1)",
subtitle="Capture HDMI display",
icon_markup=ssfull,
action=lambda: self._run_script("screenshot", "HDMI-A-1"),
relevance=0.7,
plugin_name=self.display_name,
),
] ]
) )
# Screen recording actions # Standard recording actions
results.extend( results.extend(
[ [
Result( Result(
title="Start Fullscreen Recording", title="Start Recording (eDP-1)",
subtitle="Record the entire screen", subtitle="Record the main display with audio",
icon_markup=screenrecord, icon_markup=screenrecord,
action=lambda: self.screencapture.screencast_start(fullscreen=True), action=lambda: self._run_script("record", "eDP-1"),
relevance=0.7, relevance=0.7,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
@@ -96,32 +262,138 @@ class ScreencapturePlugin(PluginBase):
title="Start Region Recording", title="Start Region Recording",
subtitle="Record a selected region", subtitle="Record a selected region",
icon_markup=screenrecord, icon_markup=screenrecord,
action=lambda: self.screencapture.screencast_start( action=lambda: self._run_script("record", "selection"),
fullscreen=False
),
relevance=0.6, relevance=0.6,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
Result( Result(
title="Start Fullscreen Recording with Audio", title="Start Recording (HDMI-A-1)",
subtitle="Record entire screen with system audio", subtitle="Record HDMI display with audio",
icon_markup=screenrecord, icon_markup=screenrecord,
action=lambda: self.screencapture.screencast_start( action=lambda: self._run_script("record", "HDMI-A-1"),
fullscreen=True, audio=True
),
relevance=0.5, relevance=0.5,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
]
)
# No-audio recording actions
results.extend(
[
Result( Result(
title="Start Region Recording with Audio", title="Start Recording No Audio (eDP-1)",
subtitle="Record selected region with system audio", subtitle="Record the main display without audio",
icon_markup=screenrecord, icon_markup=screenrecord,
action=lambda: self.screencapture.screencast_start( action=lambda: self._run_script("record-noaudio", "eDP-1"),
fullscreen=False, audio=True relevance=0.65,
), plugin_name=self.display_name,
),
Result(
title="Start Region Recording No Audio",
subtitle="Record a selected region without audio",
icon_markup=screenrecord,
action=lambda: self._run_script("record-noaudio", "selection"),
relevance=0.55,
plugin_name=self.display_name,
),
Result(
title="Start Recording No Audio (HDMI-A-1)",
subtitle="Record HDMI display without audio",
icon_markup=screenrecord,
action=lambda: self._run_script("record-noaudio", "HDMI-A-1"),
relevance=0.45,
plugin_name=self.display_name,
),
]
)
# High-quality recording actions
results.extend(
[
Result(
title="Start HQ Recording (eDP-1)",
subtitle="High-quality recording for YouTube",
icon_markup=screenrecord,
action=lambda: self._run_script("record-hq", "eDP-1"),
relevance=0.4, relevance=0.4,
plugin_name=self.display_name, plugin_name=self.display_name,
), ),
Result(
title="Start HQ Region Recording",
subtitle="High-quality region recording",
icon_markup=screenrecord,
action=lambda: self._run_script("record-hq", "selection"),
relevance=0.3,
plugin_name=self.display_name,
),
Result(
title="Start HQ Recording (HDMI-A-1)",
subtitle="High-quality HDMI recording",
icon_markup=screenrecord,
action=lambda: self._run_script("record-hq", "HDMI-A-1"),
relevance=0.2,
plugin_name=self.display_name,
),
]
)
# GIF recording actions
results.extend(
[
Result(
title="Start GIF Recording (eDP-1)",
subtitle="Record as optimized GIF",
icon_markup=screenrecord,
action=lambda: self._run_script("record-gif", "eDP-1"),
relevance=0.1,
plugin_name=self.display_name,
),
Result(
title="Start GIF Region Recording",
subtitle="Record selected region as GIF",
icon_markup=screenrecord,
action=lambda: self._run_script("record-gif", "selection"),
relevance=0.05,
plugin_name=self.display_name,
),
]
)
# Conversion actions
results.extend(
[
Result(
title="Convert to WebM",
subtitle="Convert MKV recordings to WebM format",
icon_markup=screenrecord,
action=lambda: self._run_script("convert", "webm"),
relevance=0.01,
plugin_name=self.display_name,
),
Result(
title="Convert for iPhone",
subtitle="Convert recordings for iPhone compatibility",
icon_markup=screenrecord,
action=lambda: self._run_script("convert", "iphone"),
relevance=0.01,
plugin_name=self.display_name,
),
Result(
title="Convert for YouTube",
subtitle="Convert recordings for YouTube upload",
icon_markup=screenrecord,
action=lambda: self._run_script("convert", "youtube"),
relevance=0.01,
plugin_name=self.display_name,
),
Result(
title="Convert to GIF",
subtitle="Convert video recordings to GIF",
icon_markup=screenrecord,
action=lambda: self._run_script("convert", "gif"),
relevance=0.01,
plugin_name=self.display_name,
),
] ]
) )