quickshell & script: implemented recording
This commit is contained in:
@@ -1,6 +1,15 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# https://github.com/end-4/dots-hyprland/blob/main/.config/ags/scripts/record-script.sh
|
# https://github.com/end-4/dots-hyprland/blob/main/.config/ags/scripts/record-script.sh
|
||||||
|
|
||||||
|
[ -z "$codec" ] && codec="av1_nvenc"
|
||||||
|
[ -z "$pixel_format" ] && pixel_format="p010le"
|
||||||
|
[ -z "$frame_rate" ] && frame_rate="60"
|
||||||
|
[ -z "$codec_params" ] && codec_params=\
|
||||||
|
"preset=p5 rc=vbr cq=18 \
|
||||||
|
b:v=80M maxrate=120M bufsize=160M \
|
||||||
|
color_range=tv"
|
||||||
|
[ -z "$filter_args" ] && filter_args=""
|
||||||
|
|
||||||
getdate() {
|
getdate() {
|
||||||
date '+%Y-%m-%d_%H.%M.%S'
|
date '+%Y-%m-%d_%H.%M.%S'
|
||||||
}
|
}
|
||||||
@@ -8,23 +17,42 @@ getaudiooutput() {
|
|||||||
pactl list sources | grep 'Name' | grep 'monitor' | cut -d ' ' -f2
|
pactl list sources | grep 'Name' | grep 'monitor' | cut -d ' ' -f2
|
||||||
}
|
}
|
||||||
getactivemonitor() {
|
getactivemonitor() {
|
||||||
|
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
|
||||||
hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
|
hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
|
||||||
|
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
|
||||||
|
niri msg focused-output | head -n 1 | sed -n 's/.*(\(.*\)).*/\1/p'
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recorder_args=(
|
||||||
|
--codec "$codec"
|
||||||
|
--pixel-format "$pixel_format"
|
||||||
|
--framerate "$frame_rate"
|
||||||
|
-f './recording_'"$(getdate)"'.mkv'
|
||||||
|
)
|
||||||
|
|
||||||
|
for param in $codec_params; do
|
||||||
|
recorder_args+=(-p "$param")
|
||||||
|
done
|
||||||
|
|
||||||
|
for filter in $filter_args; do
|
||||||
|
recorder_args+=(-F "$filter")
|
||||||
|
done
|
||||||
|
|
||||||
mkdir -p "$(xdg-user-dir VIDEOS)"
|
mkdir -p "$(xdg-user-dir VIDEOS)"
|
||||||
cd "$(xdg-user-dir VIDEOS)" || exit
|
cd "$(xdg-user-dir VIDEOS)" || exit
|
||||||
if pgrep wf-recorder > /dev/null; then
|
if pgrep wf-recorder > /dev/null; then
|
||||||
notify-send "Recording Stopped" "Stopped" -a 'record-script.sh' &
|
notify-send "Recording Stopped" "Stopped" -a 'record-script' &
|
||||||
pkill wf-recorder &
|
pkill wf-recorder &
|
||||||
else
|
else
|
||||||
notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'record-script.sh'
|
notify-send "Starting recording" 'recording_'"$(getdate)"'.mkv' -a 'record-script'
|
||||||
if [[ "$1" == "--sound" ]]; then
|
if [[ "$1" == "--sound" ]]; then
|
||||||
wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" --audio="$(getaudiooutput)" & disown
|
wf-recorder --geometry "$(slurp)" --audio="$(getaudiooutput)" "${recorder_args[@]}" & disown
|
||||||
elif [[ "$1" == "--fullscreen-sound" ]]; then
|
elif [[ "$1" == "--fullscreen-sound" ]]; then
|
||||||
wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio="$(getaudiooutput)" & disown
|
wf-recorder -o "$(getactivemonitor)" --audio="$(getaudiooutput)" "${recorder_args[@]}" & disown
|
||||||
elif [[ "$1" == "--fullscreen" ]]; then
|
elif [[ "$1" == "--fullscreen" ]]; then
|
||||||
wf-recorder -o $(getactivemonitor) --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t & disown
|
wf-recorder -o "$(getactivemonitor)" "${recorder_args[@]}" & disown
|
||||||
else
|
else
|
||||||
wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" & disown
|
wf-recorder --geometry "$(slurp)" "${recorder_args[@]}" & disown
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -238,15 +238,19 @@ window-rule {
|
|||||||
open-floating true
|
open-floating true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Block from recording
|
||||||
|
window-rule {
|
||||||
|
match app-id="thunderbird"
|
||||||
|
|
||||||
|
block-out-from "screen-capture"
|
||||||
|
}
|
||||||
|
|
||||||
|
// I love round corners
|
||||||
window-rule {
|
window-rule {
|
||||||
geometry-corner-radius 14
|
geometry-corner-radius 14
|
||||||
clip-to-geometry true
|
clip-to-geometry true
|
||||||
}
|
}
|
||||||
|
|
||||||
window-rule {
|
|
||||||
match at-startup=true app-id="Spotify"
|
|
||||||
open-on-workspace "special"
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************Others************************/
|
/************************Others************************/
|
||||||
|
|
||||||
@@ -289,6 +293,7 @@ binds {
|
|||||||
Mod+Shift+L { spawn-sh "qs ipc call lyrics toggleBarLyrics"; }
|
Mod+Shift+L { spawn-sh "qs ipc call lyrics toggleBarLyrics"; }
|
||||||
Mod+Shift+K { spawn-sh "pkill -x quickshell || quickshell"; }
|
Mod+Shift+K { spawn-sh "pkill -x quickshell || quickshell"; }
|
||||||
Mod+I { spawn-sh "qs ipc call idleInhibitor toggleInhibitor"; }
|
Mod+I { spawn-sh "qs ipc call idleInhibitor toggleInhibitor"; }
|
||||||
|
Mod+Alt+R { spawn-sh "qs ipc call recording startOrStopRecording"; }
|
||||||
|
|
||||||
// Rofi
|
// Rofi
|
||||||
Mod+D { spawn-sh "pkill -x rofi || rofi -show run"; }
|
Mod+D { spawn-sh "pkill -x rofi || rofi -show run"; }
|
||||||
|
|||||||
@@ -238,15 +238,19 @@ window-rule {
|
|||||||
open-floating true
|
open-floating true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Block from recording
|
||||||
|
window-rule {
|
||||||
|
match app-id="thunderbird"
|
||||||
|
|
||||||
|
block-out-from "screen-capture"
|
||||||
|
}
|
||||||
|
|
||||||
|
// I love round corners
|
||||||
window-rule {
|
window-rule {
|
||||||
geometry-corner-radius 14
|
geometry-corner-radius 14
|
||||||
clip-to-geometry true
|
clip-to-geometry true
|
||||||
}
|
}
|
||||||
|
|
||||||
window-rule {
|
|
||||||
match at-startup=true app-id="Spotify"
|
|
||||||
open-on-workspace "special"
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************Others************************/
|
/************************Others************************/
|
||||||
|
|
||||||
@@ -289,6 +293,7 @@ binds {
|
|||||||
Mod+Shift+L { spawn-sh "qs ipc call lyrics toggleBarLyrics"; }
|
Mod+Shift+L { spawn-sh "qs ipc call lyrics toggleBarLyrics"; }
|
||||||
Mod+Shift+K { spawn-sh "pkill -x quickshell || quickshell"; }
|
Mod+Shift+K { spawn-sh "pkill -x quickshell || quickshell"; }
|
||||||
Mod+I { spawn-sh "qs ipc call idleInhibitor toggleInhibitor"; }
|
Mod+I { spawn-sh "qs ipc call idleInhibitor toggleInhibitor"; }
|
||||||
|
Mod+Alt+R { spawn-sh "qs ipc call recording startOrStopRecording"; }
|
||||||
|
|
||||||
// Rofi
|
// Rofi
|
||||||
Mod+D { spawn-sh "pkill -x rofi || rofi -show run"; }
|
Mod+D { spawn-sh "pkill -x rofi || rofi -show run"; }
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"location": "Munich",
|
"location": "Munich",
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"doNotDisturb": false,
|
"doNotDisturb": false,
|
||||||
"lastSeenTs": 1760477228000
|
"lastSeenTs": 1760623982000
|
||||||
},
|
},
|
||||||
"primaryColor": "#89b4fa",
|
"primaryColor": "#89b4fa",
|
||||||
"showLyricsBar": false
|
"showLyricsBar": false
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Singleton {
|
|||||||
readonly property string speedReset: ""
|
readonly property string speedReset: ""
|
||||||
readonly property string reset: ""
|
readonly property string reset: ""
|
||||||
readonly property string lines: ""
|
readonly property string lines: ""
|
||||||
|
readonly property string record: ""
|
||||||
// Tabler icons
|
// Tabler icons
|
||||||
// Expose the font family name for easy access
|
// Expose the font family name for easy access
|
||||||
readonly property string fontFamily: currentFontLoader ? currentFontLoader.name : ""
|
readonly property string fontFamily: currentFontLoader ? currentFontLoader.name : ""
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ Variants {
|
|||||||
width: 10
|
width: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordIndicator {
|
||||||
|
}
|
||||||
|
|
||||||
Ip {
|
Ip {
|
||||||
showCountryCode: true
|
showCountryCode: true
|
||||||
}
|
}
|
||||||
|
|||||||
107
quickshell/Modules/Bar/Components/RecordIndicator.qml
Normal file
107
quickshell/Modules/Bar/Components/RecordIndicator.qml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import qs.Constants
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property color fillColor: Colors.red
|
||||||
|
property color _actualColor: Colors.red
|
||||||
|
|
||||||
|
visible: RecordService.isRecording
|
||||||
|
implicitHeight: parent.height
|
||||||
|
implicitWidth: layout.width + 10
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
id: blinkAnimation
|
||||||
|
|
||||||
|
running: RecordService.isRecording
|
||||||
|
loops: Animation.Infinite
|
||||||
|
|
||||||
|
ColorAnimation {
|
||||||
|
target: root
|
||||||
|
property: "_actualColor"
|
||||||
|
to: Qt.rgba(fillColor.r, fillColor.g, fillColor.b, 0)
|
||||||
|
duration: Style.animationSlowest
|
||||||
|
easing.type: Easing.InOutCubic
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorAnimation {
|
||||||
|
target: root
|
||||||
|
property: "_actualColor"
|
||||||
|
to: fillColor
|
||||||
|
duration: Style.animationSlowest
|
||||||
|
easing.type: Easing.InOutCubic
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: Icons.record
|
||||||
|
font.pointSize: Fonts.icon + 6
|
||||||
|
color: _actualColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: expander
|
||||||
|
|
||||||
|
implicitWidth: mouseArea.containsMouse ? ipText.implicitWidth + 10 : 0
|
||||||
|
implicitHeight: parent.height
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: ipText
|
||||||
|
|
||||||
|
text: RecordService.recordingDisplay
|
||||||
|
font.pointSize: Fonts.medium
|
||||||
|
font.family: Fonts.primary
|
||||||
|
color: fillColor
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Style.animationFast
|
||||||
|
easing.type: Easing.InOutCubic
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
|
onClicked: (mouse) => {
|
||||||
|
if (mouse.button === Qt.LeftButton)
|
||||||
|
RecordService.startOrStop();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on _actualColor {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Style.animationFast
|
||||||
|
easing.type: Easing.InOutCubic
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import QtQuick
|
|||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
import qs.Constants
|
import qs.Constants
|
||||||
import qs.Modules.Panel.Cards
|
import qs.Modules.Panel.Cards
|
||||||
import qs.Noctalia
|
import qs.Noctalia
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string cacheDir: Quickshell.env("HOME") + "/.cache/quickshell/"
|
property string cacheDir: Quickshell.env("HOME") + "/.cache/quickshell/"
|
||||||
|
property string recordingDir: Quickshell.env("HOME") + "/Videos/recordings/"
|
||||||
property var cacheFiles: ["Location.json", "Ip.json", "Notifications.json", "LyricsOffset.txt"]
|
property var cacheFiles: ["Location.json", "Ip.json", "Notifications.json", "LyricsOffset.txt"]
|
||||||
property bool loaded: false
|
property bool loaded: false
|
||||||
property string locationCacheFile: cacheDir + "Location.json"
|
property string locationCacheFile: cacheDir + "Location.json"
|
||||||
@@ -19,7 +20,7 @@ Singleton {
|
|||||||
id: process
|
id: process
|
||||||
|
|
||||||
running: true
|
running: true
|
||||||
command: ["sh", "-c", `mkdir -p ${cacheDir} && touch ${cacheDir + cacheFiles.join(` && touch ${cacheDir}`)}`]
|
command: ["sh", "-c", `mkdir -p ${cacheDir} && mkdir -p ${recordingDir} && touch ${cacheDir + cacheFiles.join(` && touch ${cacheDir}`)}`]
|
||||||
onExited: (code, status) => {
|
onExited: (code, status) => {
|
||||||
if (code === 0)
|
if (code === 0)
|
||||||
root.loaded = true;
|
root.loaded = true;
|
||||||
|
|||||||
@@ -40,4 +40,12 @@ Item {
|
|||||||
target: "idleInhibitor"
|
target: "idleInhibitor"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpcHandler {
|
||||||
|
function startOrStopRecording() {
|
||||||
|
RecordService.startOrStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
target: "recording"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ Singleton {
|
|||||||
|
|
||||||
onOffsetChanged: {
|
onOffsetChanged: {
|
||||||
if (SettingsService.showLyricsBar)
|
if (SettingsService.showLyricsBar)
|
||||||
SendNotification.show("Lyrics Offset Changed", `Current offset: ${offset} ms`, 1000);
|
SendNotification.show("Lyrics Offset Changed", `Current offset: ${offset} ms`);
|
||||||
|
|
||||||
writeOffset();
|
writeOffset();
|
||||||
}
|
}
|
||||||
|
|||||||
163
quickshell/Services/RecordService.qml
Normal file
163
quickshell/Services/RecordService.qml
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import qs.Services
|
||||||
|
import qs.Utils
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
property string recordingDir: CacheService.recordingDir
|
||||||
|
property bool isRecording: false
|
||||||
|
property bool isStopping: false
|
||||||
|
property string codec: "av1_nvenc"
|
||||||
|
property string container: "mkv"
|
||||||
|
property string pixelFormat: "p010le"
|
||||||
|
property string recordingDisplay: ""
|
||||||
|
property int framerate: 60
|
||||||
|
property var codecParams: ["preset=p5", "rc=vbr", "cq=18", "b:v=80M", "maxrate=120M", "bufsize=160M", "color_range=tv"]
|
||||||
|
property var filterArgs: []
|
||||||
|
|
||||||
|
function getFilename() {
|
||||||
|
var d = new Date();
|
||||||
|
var year = d.getFullYear();
|
||||||
|
var month = ("0" + (d.getMonth() + 1)).slice(-2);
|
||||||
|
var day = ("0" + d.getDate()).slice(-2);
|
||||||
|
var hours = ("0" + d.getHours()).slice(-2);
|
||||||
|
var minutes = ("0" + d.getMinutes()).slice(-2);
|
||||||
|
var seconds = ("0" + d.getSeconds()).slice(-2);
|
||||||
|
return "recording_" + year + "-" + month + "-" + day + "_" + hours + "." + minutes + "." + seconds + "." + container;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAudioSink() {
|
||||||
|
return AudioService.sink ? AudioService.sink.name + '.monitor' : null; // this works on my machine :)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVideoSource(callback) {
|
||||||
|
if (niriFocusedOutputProcess.running) {
|
||||||
|
Logger.warn("RecordService", "Already fetching focused output, returning null.");
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
niriFocusedOutputProcess.onGetName = callback;
|
||||||
|
niriFocusedOutputProcess.running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startOrStop() {
|
||||||
|
if (isRecording)
|
||||||
|
stop();
|
||||||
|
else
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
if (!isRecording) {
|
||||||
|
Logger.warn("RecordService", "Not currently recording, cannot stop.");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
if (isStopping) {
|
||||||
|
Logger.warn("RecordService", "Already stopping, please wait.");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
isStopping = true;
|
||||||
|
recordProcess.signal(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
if (isRecording || isStopping) {
|
||||||
|
Logger.warn("RecordService", "Already recording, cannot start.");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
isRecording = true;
|
||||||
|
getVideoSource((source) => {
|
||||||
|
if (!source) {
|
||||||
|
SendNotification.show("Recording failed", "Could not determine which display to record from.");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
recordingDisplay = source;
|
||||||
|
const audioSink = getAudioSink();
|
||||||
|
if (!audioSink) {
|
||||||
|
SendNotification.show("Recording failed", "No audio sink available to record from.");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
recordProcess.filePath = recordingDir + getFilename();
|
||||||
|
recordProcess.command = ["wf-recorder", "--audio=" + audioSink, "-o", source, "--codec", codec, "--pixel-format", pixelFormat, "--framerate", framerate.toString(), "-f", recordProcess.filePath];
|
||||||
|
for (const param of codecParams) {
|
||||||
|
recordProcess.command.push("-p");
|
||||||
|
recordProcess.command.push(param);
|
||||||
|
}
|
||||||
|
for (const filter of filterArgs) {
|
||||||
|
recordProcess.command.push("-F");
|
||||||
|
recordProcess.command.push(filter);
|
||||||
|
}
|
||||||
|
Logger.log("RecordService", "Starting recording with command: " + recordProcess.command.join(" "));
|
||||||
|
recordProcess.onErrorExit = function() {
|
||||||
|
SendNotification.show("Recording failed", "An error occurred while trying to record the screen.");
|
||||||
|
};
|
||||||
|
recordProcess.onNormalExit = function() {
|
||||||
|
SendNotification.show("Recording stopped", recordProcess.filePath);
|
||||||
|
};
|
||||||
|
recordProcess.running = true;
|
||||||
|
SendNotification.show("Recording started", "Recording to " + recordProcess.filePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: recordProcess
|
||||||
|
|
||||||
|
property string filePath: ""
|
||||||
|
property var onNormalExit: null
|
||||||
|
property var onErrorExit: null
|
||||||
|
|
||||||
|
running: false
|
||||||
|
onExited: function(exitCode, exitStatus) {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
Logger.log("RecordService", "Recording stopped successfully.");
|
||||||
|
if (onNormalExit) {
|
||||||
|
onNormalExit();
|
||||||
|
onNormalExit = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger.error("RecordService", "Recording process exited with error code: " + exitCode);
|
||||||
|
if (onErrorExit) {
|
||||||
|
onErrorExit();
|
||||||
|
onErrorExit = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isRecording = false;
|
||||||
|
isStopping = false;
|
||||||
|
recordingDisplay = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: niriFocusedOutputProcess
|
||||||
|
|
||||||
|
property var onGetName: null
|
||||||
|
|
||||||
|
running: false
|
||||||
|
command: ["niri", "msg", "focused-output"]
|
||||||
|
onExited: function(exitCode, exitStatus) {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
Logger.error("RecordService", "Failed to get focused output via niri.");
|
||||||
|
if (niriFocusedOutputProcess.onGetName) {
|
||||||
|
niriFocusedOutputProcess.onGetName(null);
|
||||||
|
niriFocusedOutputProcess.onGetName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout: SplitParser {
|
||||||
|
splitMarker: "\n"
|
||||||
|
onRead: (data) => {
|
||||||
|
if (niriFocusedOutputProcess.onGetName) {
|
||||||
|
const parts = data.split(' ');
|
||||||
|
const name = parts.length > 0 ? parts[parts.length - 1].slice(1)?.slice(0, -1) : null;
|
||||||
|
name ? Logger.log("RecordService", "Focused output is: " + name) : Logger.warn("RecordService", "No focused output found.");
|
||||||
|
niriFocusedOutputProcess.onGetName(name);
|
||||||
|
niriFocusedOutputProcess.onGetName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,11 +6,11 @@ pragma Singleton
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
function show(title, message, timeout = 5000, icon = "", urgency = "normal") {
|
function show(title, message, icon = "", urgency = "normal") {
|
||||||
if (icon)
|
if (icon)
|
||||||
Quickshell.execDetached(["notify-send", "-u", urgency, "-i", icon, "-t", timeout.toString(), title, message, "-a", "quickshell"]);
|
Quickshell.execDetached(["notify-send", "-u", urgency, "-i", icon, title, message, "-a", "quickshell"]);
|
||||||
else
|
else
|
||||||
Quickshell.execDetached(["notify-send", "-u", urgency, "-t", timeout.toString(), title, message, "-a", "quickshell"]);
|
Quickshell.execDetached(["notify-send", "-u", urgency, title, message, "-a", "quickshell"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user