forked from Shinonome/dots-hyprland
overview: add music recognition button to search bar
This commit is contained in:
@@ -357,8 +357,8 @@ Singleton {
|
|||||||
property real mediaControlsHeight: 160
|
property real mediaControlsHeight: 160
|
||||||
property real notificationPopupWidth: 410
|
property real notificationPopupWidth: 410
|
||||||
property real osdWidth: 180
|
property real osdWidth: 180
|
||||||
property real searchWidthCollapsed: 260
|
property real searchWidthCollapsed: 210
|
||||||
property real searchWidth: 400
|
property real searchWidth: 360
|
||||||
property real sidebarWidth: 460
|
property real sidebarWidth: 460
|
||||||
property real sidebarWidthExtended: 750
|
property real sidebarWidthExtended: 750
|
||||||
property real baseVerticalBarWidth: 46
|
property real baseVerticalBarWidth: 46
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ToolbarButton {
|
|||||||
colBackgroundToggled: Appearance.colors.colSecondaryContainer
|
colBackgroundToggled: Appearance.colors.colSecondaryContainer
|
||||||
colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover
|
colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover
|
||||||
colRippleToggled: Appearance.colors.colSecondaryContainerActive
|
colRippleToggled: Appearance.colors.colSecondaryContainerActive
|
||||||
|
property color colText: toggled ? Appearance.colors.colOnSecondaryContainer : Appearance.colors.colOnSurfaceVariant
|
||||||
|
|
||||||
contentItem: MaterialSymbol {
|
contentItem: MaterialSymbol {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -16,6 +17,6 @@ ToolbarButton {
|
|||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
iconSize: 22
|
iconSize: 22
|
||||||
text: iconBtn.text
|
text: iconBtn.text
|
||||||
color: iconBtn.toggled ? Appearance.colors.colOnSecondaryContainer : Appearance.colors.colOnSurfaceVariant
|
color: iconBtn.colText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ RowLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// background: null
|
|
||||||
|
|
||||||
cursorDelegate: Rectangle {
|
cursorDelegate: Rectangle {
|
||||||
width: 1
|
width: 1
|
||||||
color: searchInput.activeFocus ? Appearance.colors.colPrimary : "transparent"
|
color: searchInput.activeFocus ? Appearance.colors.colPrimary : "transparent"
|
||||||
@@ -102,10 +100,58 @@ RowLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IconToolbarButton {
|
IconToolbarButton {
|
||||||
|
Layout.topMargin: 4
|
||||||
|
Layout.bottomMargin: 4
|
||||||
onClicked: {
|
onClicked: {
|
||||||
GlobalStates.overviewOpen = false;
|
GlobalStates.overviewOpen = false;
|
||||||
Hyprland.dispatch("global quickshell:regionSearch")
|
Hyprland.dispatch("global quickshell:regionSearch")
|
||||||
}
|
}
|
||||||
text: "image_search"
|
text: "image_search"
|
||||||
|
StyledToolTip {
|
||||||
|
text: Translation.tr("Google Lens")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconToolbarButton {
|
||||||
|
id: songRecButton
|
||||||
|
Layout.topMargin: 4
|
||||||
|
Layout.bottomMargin: 4
|
||||||
|
Layout.rightMargin: 4
|
||||||
|
toggled: SongRec.running
|
||||||
|
onClicked: SongRec.toggleRunning()
|
||||||
|
text: "music_cast"
|
||||||
|
|
||||||
|
StyledToolTip {
|
||||||
|
text: Translation.tr("Recognize music")
|
||||||
|
}
|
||||||
|
|
||||||
|
colText: toggled ? Appearance.colors.colOnPrimary : Appearance.colors.colOnSurfaceVariant
|
||||||
|
background: MaterialShape {
|
||||||
|
RotationAnimation on rotation {
|
||||||
|
running: songRecButton.toggled
|
||||||
|
duration: 12000
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
loops: Animation.Infinite
|
||||||
|
from: 0
|
||||||
|
to: 360
|
||||||
|
}
|
||||||
|
shape: {
|
||||||
|
if (songRecButton.down) {
|
||||||
|
return songRecButton.toggled ? MaterialShape.Shape.Circle : MaterialShape.Shape.Square
|
||||||
|
} else {
|
||||||
|
return songRecButton.toggled ? MaterialShape.Shape.SoftBurst : MaterialShape.Shape.Circle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color: {
|
||||||
|
if (songRecButton.toggled) {
|
||||||
|
return songRecButton.hovered ? Appearance.colors.colPrimaryHover : Appearance.colors.colPrimary
|
||||||
|
} else {
|
||||||
|
return songRecButton.hovered ? Appearance.colors.colSurfaceContainerHigh : ColorUtils.transparentize(Appearance.colors.colSurfaceContainerHigh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on color {
|
||||||
|
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-76
@@ -10,93 +10,23 @@ import qs.services
|
|||||||
AndroidQuickToggleButton {
|
AndroidQuickToggleButton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int timeoutInterval: Config.options.musicRecognition.interval
|
toggled: SongRec.running
|
||||||
property int timeoutDuration: Config.options.musicRecognition.timeout
|
property bool sourceIsMonitor: SongRec.monitorSource === SongRec.MonitorSource.Monitor
|
||||||
|
|
||||||
|
|
||||||
property string monitorSource: "monitor" // "monitor" (system sound) , "input" (microphone)
|
|
||||||
|
|
||||||
name: Translation.tr("Identify Music")
|
name: Translation.tr("Identify Music")
|
||||||
statusText: toggled ? Translation.tr("Listening...") : monitorSource === "monitor" ? Translation.tr("System sound") : Translation.tr("Microphone")
|
statusText: toggled ? Translation.tr("Listening...") : sourceIsMonitor ? Translation.tr("System sound") : Translation.tr("Microphone")
|
||||||
toggled: false
|
buttonIcon: toggled ? "music_cast" : (sourceIsMonitor ? "music_note" : "frame_person_mic")
|
||||||
buttonIcon: toggled ? "music_cast" : (monitorSource === "monitor" ? "music_note" : "frame_person_mic")
|
|
||||||
|
|
||||||
property var recognizedTrack: ({ title:"", subtitle:"", url:""})
|
|
||||||
|
|
||||||
function handleRecognition(jsonText) {
|
|
||||||
try {
|
|
||||||
var obj = JSON.parse(jsonText)
|
|
||||||
root.recognizedTrack = {
|
|
||||||
title: obj.track.title,
|
|
||||||
subtitle: obj.track.subtitle,
|
|
||||||
url: obj.track.url
|
|
||||||
}
|
|
||||||
musicReconizedProc.running = true
|
|
||||||
} catch(e) {
|
|
||||||
Quickshell.execDetached(["notify-send", Translation.tr("Couldn't recognize music"), Translation.tr("Perhaps what you're listening to is too niche"), "-a", "Shell"])
|
|
||||||
} finally {
|
|
||||||
root.toggled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StyledToolTip {
|
StyledToolTip {
|
||||||
text: Translation.tr("Recognize music | Right-click to toggle source")
|
text: Translation.tr("Recognize music | Right-click to toggle source")
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.toggled = !root.toggled
|
SongRec.toggleRunning()
|
||||||
recognizeMusicProc.running = root.toggled
|
|
||||||
musicReconizedProc.running = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
altAction: () => {
|
altAction: () => {
|
||||||
if (root.monitorSource === "monitor"){
|
SongRec.toggleMonitorSource()
|
||||||
root.monitorSource = "input"
|
|
||||||
return
|
|
||||||
}else {
|
|
||||||
root.monitorSource = "monitor"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
id: recognizeMusicProc
|
|
||||||
running: false
|
|
||||||
command: [`${Directories.scriptPath}/musicRecognition/recognize-music.sh`, "-i", root.timeoutInterval, "-t", root.timeoutDuration, "-s", root.monitorSource]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
handleRecognition(this.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onExited: (exitCode, exitStatus) => {
|
|
||||||
if (exitCode === 1) {
|
|
||||||
Quickshell.execDetached(["notify-send", Translation.tr("Couldn't recognize music"), Translation.tr("Make sure you have songrec installed"), "-a", "Shell"])
|
|
||||||
root.toggled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: musicReconizedProc
|
|
||||||
running: false
|
|
||||||
command: [
|
|
||||||
"notify-send",
|
|
||||||
Translation.tr("Music Recognized"),
|
|
||||||
root.recognizedTrack.title + " - " + root.recognizedTrack.subtitle,
|
|
||||||
"-A", "Shazam",
|
|
||||||
"-A", "YouTube",
|
|
||||||
"-a", "Shell"
|
|
||||||
]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
if (this.text === "") return
|
|
||||||
if (this.text == 0){
|
|
||||||
Qt.openUrlExternally(root.recognizedTrack.url);
|
|
||||||
} else {
|
|
||||||
Qt.openUrlExternally("https://www.youtube.com/results?search_query=" + root.recognizedTrack.title + " - " + root.recognizedTrack.subtitle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import qs.modules.common
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
enum MonitorSource { Monitor, Input }
|
||||||
|
|
||||||
|
property var monitorSource: SongRec.MonitorSource.Monitor
|
||||||
|
property int timeoutInterval: Config.options.musicRecognition.interval
|
||||||
|
property int timeoutDuration: Config.options.musicRecognition.timeout
|
||||||
|
readonly property bool running: recognizeMusicProc.running
|
||||||
|
|
||||||
|
function toggleRunning(running) {
|
||||||
|
if (recognizeMusicProc.running && !running === true) root.manuallyStopped = true;
|
||||||
|
if (running != undefined) {
|
||||||
|
recognizeMusicProc.running = running
|
||||||
|
} else {
|
||||||
|
recognizeMusicProc.running = !root.running
|
||||||
|
}
|
||||||
|
musicReconizedProc.running = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleMonitorSource(source) {
|
||||||
|
if (source !== undefined) {
|
||||||
|
root.monitorSource = source
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root.monitorSource = (root.monitorSource === SongRec.MonitorSource.Monitor) ? SongRec.MonitorSource.Input : SongRec.MonitorSource.Monitor
|
||||||
|
}
|
||||||
|
function monitorSourceToString(source) {
|
||||||
|
if (source === SongRec.MonitorSource.Monitor) {
|
||||||
|
return "monitor"
|
||||||
|
} else {
|
||||||
|
return "input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property string monitorSourceString: monitorSourceToString(monitorSource)
|
||||||
|
property var recognizedTrack: ({ title:"", subtitle:"", url:""})
|
||||||
|
property bool manuallyStopped: false
|
||||||
|
|
||||||
|
function handleRecognition(jsonText) {
|
||||||
|
try {
|
||||||
|
var obj = JSON.parse(jsonText)
|
||||||
|
root.recognizedTrack = {
|
||||||
|
title: obj.track.title,
|
||||||
|
subtitle: obj.track.subtitle,
|
||||||
|
url: obj.track.url
|
||||||
|
}
|
||||||
|
musicReconizedProc.running = true
|
||||||
|
} catch(e) {
|
||||||
|
Quickshell.execDetached(["notify-send", Translation.tr("Couldn't recognize music"), Translation.tr("Perhaps what you're listening to is too niche"), "-a", "Shell"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: recognizeMusicProc
|
||||||
|
running: false
|
||||||
|
command: [`${Directories.scriptPath}/musicRecognition/recognize-music.sh`, "-i", root.timeoutInterval, "-t", root.timeoutDuration, "-s", root.monitorSourceString]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
if (root.manuallyStopped) {
|
||||||
|
root.manuallyStopped = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handleRecognition(this.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onExited: (exitCode, exitStatus) => {
|
||||||
|
if (exitCode === 1) {
|
||||||
|
Quickshell.execDetached(["notify-send", Translation.tr("Couldn't recognize music"), Translation.tr("Make sure you have songrec installed"), "-a", "Shell"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: musicReconizedProc
|
||||||
|
running: false
|
||||||
|
command: [
|
||||||
|
"notify-send",
|
||||||
|
Translation.tr("Music Recognized"),
|
||||||
|
root.recognizedTrack.title + " - " + root.recognizedTrack.subtitle,
|
||||||
|
"-A", "Shazam",
|
||||||
|
"-A", "YouTube",
|
||||||
|
"-a", "Shell"
|
||||||
|
]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
if (this.text === "") return
|
||||||
|
if (this.text == 0) {
|
||||||
|
Qt.openUrlExternally(root.recognizedTrack.url);
|
||||||
|
} else {
|
||||||
|
Qt.openUrlExternally("https://www.youtube.com/results?search_query=" + root.recognizedTrack.title + " - " + root.recognizedTrack.subtitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user