diff --git a/cava/config b/cava/config index 18ce8de..ffcfe12 100644 --- a/cava/config +++ b/cava/config @@ -11,21 +11,21 @@ ; mode = normal # Accepts only non-negative values. -; framerate = 60 +framerate = 60 # 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off # new as of 0.6.0 autosens of low values (dynamic range) # 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0 -; autosens = 1 +autosens = 1 ; overshoot = 20 # Manual sensitivity in %. If autosens is enabled, this will only be the initial value. # 200 means double height. Accepts only non-negative values. -; sensitivity = 100 +sensitivity = 40 # The number of bars (0-512). 0 sets it to auto (fill up console). # Bars' width and space between bars in number of characters. -bars = 64 +bars = 32 ; bar_width = 2 ; bar_spacing = 1 # bar_height is only used for output in "noritake" format @@ -40,7 +40,7 @@ bars = 64 ; bar_spacing = 0 # ceter bars in terminal, if there is space. -; center_align = 1 +center_align = 0 # max height of bars in terminal, in percent of terminal height. ; max_height = 100 @@ -176,9 +176,9 @@ method = raw # 'mono' outputs left to right lowest to highest frequencies. # 'mono_option' set mono to either take input from 'left', 'right' or 'average'. # set 'reverse' to 1 to display frequencies the other way around. -; channels = stereo -; mono_option = average -; reverse = 0 +channels = mono +mono_option = average +reverse = 0 # Only valid if orientation is set to 'horizontal'. # Set 'horizontal_stereo' to 1 to have left channel bars at top and right channel at bottom. @@ -202,8 +202,8 @@ ascii_max_range = 100 # Ascii delimiters. In ascii format each bar and frame is separated by a delimiters. # Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)). -; bar_delimiter = 59 -; frame_delimiter = 10 +bar_delimiter = 59 +frame_delimiter = 10 # sdl window size and position. -1,-1 is centered. ; sdl_width = 1024 diff --git a/cava/example_config b/cava/example_config new file mode 100644 index 0000000..b8acd7f --- /dev/null +++ b/cava/example_config @@ -0,0 +1,332 @@ +## Configuration file for CAVA. + +# Lines starting with ; show config parameters and default values. +# Remove the ; to change parameters. + +[general] + +# Auto reload config if the configuration file has changed. 1 = on, 0 = off. +; live-config = 0 + +# Accepts only non-negative values. +; framerate = 60 + +# 'autosens' will attempt to decrease sensitivity if the bars peak and increase slowly as +# long as the bars don't peak. 0 = off, 1 = normal, 2..n = more aggressive. +# increase to make sensitivity increase even faster. +; autosens = 1 + +# Manual sensitivity in %. If autosens is enabled, this will only be the initial value. +# 200 means double height. Accepts only non-negative values. +; sensitivity = 100 + +# The number of bars (0-512). 0 sets it to auto (fill up console). +# Bars' width and space between bars in number of characters. +; bars = 0 +; bar_width = 2 +; bar_spacing = 1 +# bar_height is only used for output in "noritake" format +; bar_height = 32 + +# For SDL width and space between bars is in pixels, defaults are: +; bar_width = 20 +; bar_spacing = 5 + +# sdl_glsl have these default values, they are only used to calculate max number of bars. +; bar_width = 1 +; bar_spacing = 0 + +# center bars in terminal, if there is space. +center_align = 0 + +# max height of bars in terminal, in percent of terminal height. +; max_height = 100 + +# Lower and higher cutoff frequencies for lowest and highest bars +# the bandwidth of the visualizer. +# Note: there is a minimum total bandwidth of 43Mhz x number of bars. +# Cava will automatically increase the higher cutoff frequency if needed to satisfy the minimum bandwidth. +; lower_cutoff_freq = 50 +; higher_cutoff_freq = 10000 + +# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and +# only check for input once per second. Cava will wake up once input is detected. 0 = disable. +; sleep_timer = 0 + + +[input] + +# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss', 'jack' or 'shmem' +# Defaults to 'oss', 'pipewire', 'sndio', 'jack', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with. +# On Mac it defaults to 'portaudio' or 'fifo' +# On Windows this is automatic and no input settings are needed. +# +# Each input method uses the same config variable 'source' +# to define where it should get the audio. +# +# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink +# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them). +# +# For pipewire 'source' will be the object name or object.serial of the device to capture from. +# Both input and output devices are supported. To capture the monitor source of a sink node, append '.monitor' to the sink's object name. +# +# For alsa 'source' will be the capture device. +# For fifo 'source' will be the path to fifo-file. +# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address +# +# For sndio 'source' will be a raw recording audio descriptor or a monitoring sub-device, e.g. 'rsnd/2' or 'snd/1'. Default: 'default'. +# README.md contains further information on how to setup CAVA for sndio. +# +# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device. +# README.md contains further information on how to setup CAVA for OSS on FreeBSD. +# +# For jack 'source' will be the name of the JACK server to connect to, e.g. 'foobar'. Default: 'default'. +# README.md contains further information on how to setup CAVA for JACK. +# +; method = pulse +; source = auto + +; method = pipewire +; source = auto + +; method = alsa +; source = hw:Loopback,1 + +; method = fifo +; source = /tmp/mpd.fifo + +; method = shmem +; source = /squeezelite-AA:BB:CC:DD:EE:FF + +; method = portaudio +; source = auto + +; method = sndio +; source = default + +; method = oss +; source = /dev/dsp + +; method = jack +; source = default + +# The options 'sample_rate', 'sample_bits', 'channels' and 'autoconnect' can be configured for some input methods: +# sample_rate: fifo, pipewire, sndio, oss +# sample_bits: fifo, pipewire, sndio, oss +# channels: sndio, oss, jack +# autoconnect: jack +# Other methods ignore these settings. +# For pipewire, sample_rate will default to 48000, for all other input methods, sample_rate will default to 44100. +# +# For 'sndio' and 'oss' they are only preferred values, i.e. if the values are not supported +# by the chosen audio device, the device will use other supported values instead. +# Example: 48000, 32 and 2, but the device only supports 44100, 16 and 1, then it +# will use 44100, 16 and 1. +# +# +# The 'pipewire' input method has three options to control linking and mixing: +# active: Force the node to always process. Useful for monitoring sources when no other application is active. +# remix: Allow pipewire to remix audio channels to match cava's channel count. Useful for surround sound. +# virtual: Set the node to virtual, to avoid recording notifications from the DE. +# +; sample_rate = 44100 +; sample_bits = 16 +; channels = 2 +; autoconnect = 2 +; active = 1 +; remix = 1 +; virtual = 1 + + +[output] + +# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl' +# or 'sdl_glsl'. +# 'noncurses' (default) uses a buffer and cursor movements to only print +# changes from frame to frame in the terminal. Uses less resources and is less +# prone to tearing (vsync issues) than 'ncurses'. +# +# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data +# stream of the bar heights that can be used to send to other applications. +# 'raw' defaults to 1024 bars stereo (512 bars mono), which can be adjusted in the 'bars' option above. +# +# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display +# in graphic mode. It only support the 3000 series graphical VFDs for now. +# +# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context. +# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or +# use one of the predefined ones. +; method = noncurses + +# Orientation of the visualization. Can be 'bottom', 'top', 'left', 'right' or +# 'horizontal'. Default is 'bottom'. 'left and 'right' are only supported on sdl +# and ncurses output. 'horizontal' (bars go up and down from center) is only supported +# on noncurses output. +# Note: many fonts have weird or missing glyphs for characters used in orientations +# other than 'bottom', which can make output not look right. +orientation = bottom + +# Visual channels. Can be 'stereo' or 'mono'. +# 'stereo' mirrors both channels with low frequencies in center. +# 'mono' outputs left to right lowest to highest frequencies. +# 'mono_option' set mono to either take input from 'left', 'right' or 'average'. +# set 'reverse' to 1 to display frequencies the other way around. +channels = mono +mono_option = average +reverse = 0 + +# Only valid if orientation is set to 'horizontal'. +# Set 'horizontal_stereo' to 1 to have left channel bars at top and right channel at bottom. +# Set 'left_bottom' to 0 to have right channel at top and left channel at bottom. +; horizontal_stereo = 0 +; left_bottom = 1 + +# Raw output target. +# On Linux, a fifo will be created if target does not exist. +# On Windows, a named pipe will be created if target does not exist. +; raw_target = /dev/stdout + +# Raw data format. Can be 'binary' or 'ascii'. +; data_format = binary + +# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530). +; bit_format = 16bit + +# Ascii max value. In 'ascii' mode range will run from 0 to value specified here +; ascii_max_range = 1000 + +# Ascii delimiters. In ascii format each bar and frame is separated by a delimiter. +# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)). +; bar_delimiter = 59 +; frame_delimiter = 10 + +# sdl window size and position. -1,-1 is centered. +; sdl_width = 1024 +; sdl_height = 512 +; sdl_x = -1 +; sdl_y= -1 +; sdl_full_screen = 0 + +# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none' +# 'frequency' displays the lower cut off frequency of the bar above. +# Only supported on ncurses and noncurses output. +; xaxis = none + +# enable synchronized sync. 1 = on, 0 = off +# removes flickering in alacritty terminal emulator. +# defaults to off since the behaviour in other terminal emulators is unknown +; synchronized_sync = 0 + +# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders +; vertex_shader = pass_through.vert + +# Default spectrum shader +# default value: bar_spectrum.frag +; fragment_shader = bar_spectrum.frag + +# other styles shaders +; fragment_shader = eye_of_phi.frag +; fragment_shader = northern_lights.frag +; fragment_shader = spectrogram.frag +; fragment_shader = winamp_line_style_spectrum.frag + +# Orion shaders (use with: method = sdl_glsl) +# Static Orion +; fragment_shader = orion_circle.frag +# Rotating Orion +; fragment_shader = orion_circle_rotate.frag +# Orion saturn subring +; fragment_shader = orion_saturn_subring.frag +# Orion saturn core +; fragment_shader = orion_saturn_core.frag + +# For glsl output mode, keep rendering even if no audio. 1 = on, 0 = off. Default: 0 +# Enable for animated shaders so time-based effects keep updating. +; continuous_rendering = 0 + +# SDL_GLSL only: gain applied to bar amplitudes before sending to shaders, in percent. Default: 100 +# 0 = mute, 100 = unchanged, >100 = amplify (shader input is clamped to the [0..1] range). +; sdl_glsl_gain = 100 + +# disable console blank (screen saver) in tty. 1 = on, 0 = off. Default: 0 +# (Not supported on FreeBSD) +; disable_blanking = 0 + +# show a flat bar at the bottom of the screen when idle, 1 = on, 0 = off +; show_idle_bar_heads = 1 + +# show waveform instead of frequency spectrum, 1 = on, 0 = off +; waveform = 0 + + +[color] + +# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow. +# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors require +# a terminal that can change color definitions such as Gnome-terminal or rxvt. +# default is to keep current terminal color +; background = default +; foreground = default + +# SDL and sdl_glsl only support hex code colors, these are the default: +; background = '#111111' +; foreground = '#33ffff' + +# Gradient mode, only hex defined colors are supported, +# background must also be defined in hex or remain commented out. 1 = on, 0 = off. +# You can define as many as 8 different colors. They range from bottom to top of the screen +; gradient = 0 +; gradient_color_1 = '#59cc33' +; gradient_color_2 = '#80cc33' +; gradient_color_3 = '#a6cc33' +; gradient_color_4 = '#cccc33' +; gradient_color_5 = '#cca633' +; gradient_color_6 = '#cc8033' +; gradient_color_7 = '#cc5933' +; gradient_color_8 = '#cc3333' + +# Horizontal is only supported on noncurses output. +# Only one color will be calculated per bar. +; horizontal_gradient = 0 +; horizontal_gradient_color_1 = '#c45161' +; horizontal_gradient_color_2 = '#e094a0' +; horizontal_gradient_color_3 = '#f2b6c0' +; horizontal_gradient_color_4 = '#f2dde1' +; horizontal_gradient_color_5 = '#cbc7d8' +; horizontal_gradient_color_6 = '#8db7d2' +; horizontal_gradient_color_7 = '#5e62a9' +; horizontal_gradient_color_8 = '#434279' + +# If both vertical and horizontal gradients are enabled, the vertical one will be blended in this direction. +# Can be 'up', 'down', 'left' or 'right'. 'up' means the vertical gradient will be blended in from +# bottom to top. I.e. the bottom will only be the horizontal +# and top will only be the vertical color of the gradient. +; blend_direction = 'up' + +# use theme file instead of defining colors in this file +# themes are located in $HOME/.config/cava/themes +; theme = 'none' + + +[smoothing] + +# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable. +; monstercat = 0 +; waves = 0 + +# Noise reduction, int 0 - 100. default 77 +# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth +# 100 will be very slow and smooth, 0 will be fast but noisy. +; noise_reduction = 77 + + +[eq] + +# This one is tricky. You can have as many keys as you want. +# Remember to uncomment more than one key! More keys = more precision. +# Look at readme.md on github for further explanations and examples. +; 1 = 1 # bass +; 2 = 1 +; 3 = 1 # midtone +; 4 = 1 +; 5 = 1 # treble \ No newline at end of file diff --git a/hypr/autostart.conf b/hypr/autostart.conf index a7a91ff..5fdb4e8 100644 --- a/hypr/autostart.conf +++ b/hypr/autostart.conf @@ -4,4 +4,4 @@ exec-once = /usr/bin/qs & # quickshell exec-once = awww-daemon # wallpaper exec-once = hyprsunset # night light exec-once = qs -c overview # workspace switcher https://github.com/Shanu-Kumawat/quickshell-overview -exec-once = cava -p ~/.config/cava/config \ No newline at end of file +# exec-once = cava -p ~/.config/cava/config \ No newline at end of file diff --git a/hypr/input.conf b/hypr/input.conf index b4305aa..13a17e1 100644 --- a/hypr/input.conf +++ b/hypr/input.conf @@ -12,7 +12,7 @@ input { follow_mouse = 1 - sensitivity = 0 # -1.0 - 1.0, 0 means no modification. + sensitivity = -0.8 # -1.0 - 1.0, 0 means no modification. touchpad { natural_scroll = false diff --git a/quickshell/services/CavaService.qml b/quickshell/services/CavaService.qml index 6803c41..747af1a 100644 --- a/quickshell/services/CavaService.qml +++ b/quickshell/services/CavaService.qml @@ -4,23 +4,22 @@ import Quickshell.Io Item { id: root - + signal cavaDataChanged(string data) - - // Process { - // id: cavaProcess - // command: ["cat", "/tmp/cava.fifo"] - - // stdout: StdioCollector { - // waitForEnd: false - // onStreamFinished: { - // console.log("Cava data: " + this.text) - // root.cavaDataChanged(this.text) - // } - // } - // } - - Component.onCompleted: { - cavaProcess.running = true + + Process { + id: cavaProcess + command: ["cat", "/tmp/cava.fifo"] + + stdout: SplitParser { + splitMarker: "\n" // fires onRead() for each newline-delimited chunk + onRead: data => { + root.cavaDataChanged(data); + } + } } -} \ No newline at end of file + + Component.onCompleted: { + cavaProcess.running = true; + } +} diff --git a/quickshell/ui/NowPlaying.qml b/quickshell/ui/NowPlaying.qml index 7107c7e..90e49ca 100644 --- a/quickshell/ui/NowPlaying.qml +++ b/quickshell/ui/NowPlaying.qml @@ -1,9 +1,9 @@ - import QtQuick import QtQuick.Layouts import "../constants" import "../services" + Row { id: root @@ -12,10 +12,12 @@ Row { property string artUrl: "" property int maxTextLength: 50 + property int numBands: 32 + // if the artist - title text is too long, truncate it readonly property string displayText: { - const fullText = artist !== "" ? (artist + " - " + title) : title - return fullText.length > maxTextLength ? fullText.substring(0, maxTextLength - 3) + "..." : fullText + const fullText = artist !== "" ? (artist + " - " + title) : title; + return fullText.length > maxTextLength ? fullText.substring(0, maxTextLength - 3) + "..." : fullText; } visible: title !== "" @@ -27,20 +29,6 @@ Row { // where each number represents the amplitude of a frequency band. // this can be used to create a simple visualizer // also add cava to autostart - Canvas { - // implicitWidth: parent.implicitWidth - // implicitHeight: parent.implicitHeight - // anchors.fill: parent - } - - CavaService { - id: cavaService - onCavaDataChanged: { - // TODO update the canvas with the new data - // console.log("Cava data changed: " + data) - } - } - Image { width: 18 height: 18 @@ -50,11 +38,107 @@ Row { } Text { + id: titleText text: root.displayText color: Colors.md3.primary font.family: Constants.fontFamily font.pixelSize: Constants.fontSize anchors.verticalCenter: parent.verticalCenter - z: 1 + // z: 1 } -} \ No newline at end of file + + Item { + id: titleArea + anchors.bottom: parent.bottom + width: titleText.implicitWidth + height: Math.max(titleText.implicitHeight, visualizer.height) + + // Canvas { + // id: visualizer + // anchors.fill: parent + + // property var cavaData: [] + // property var smoothedData: [] + // property real inputMax: 20 + // property real attackAlpha: 1.0 + // property real releaseAlpha: 0.9 + // property real maxStepPerFrame: 50 + // property bool needsInit: true + + // Component.onCompleted: { + // for (let i = 0; i < root.numBands; i++) { + // cavaData[i] = 0; + // smoothedData[i] = 0; + // } + // needsInit = false; + // } + + // function updateData(csvLine) { + // // Fast in-place parse: split once, parse directly into pre-allocated array + // let parts = csvLine.split(";"); + // let idx = 0; + // for (let j = 0; j < parts.length && idx < root.numBands; j++) { + // let val = Number(parts[j]); + // if (!isNaN(val)) + // cavaData[idx++] = Math.min(100, Math.max(0, val)); + // } + // while (idx < root.numBands) + // cavaData[idx++] = 0; + + // if (needsInit) { + // for (let i = 0; i < root.numBands; i++) + // smoothedData[i] = cavaData[i]; + // needsInit = false; + // } else { + // // Two-speed smoothing in place with early exit if no significant change + // let changed = false; + // for (let i = 0; i < root.numBands; i++) { + // let prev = smoothedData[i]; + // let next = cavaData[i]; + // let alpha = next >= prev ? attackAlpha : releaseAlpha; + // let blended = prev + (next - prev) * alpha; + // let delta = blended - prev; + // if (Math.abs(delta) > 0.1) + // changed = true; + // if (delta > maxStepPerFrame) + // blended = prev + maxStepPerFrame; + // else if (delta < -maxStepPerFrame) + // blended = prev - maxStepPerFrame; + // smoothedData[i] = blended; + // } + // if (!changed) + // return; + // } + + // visualizer.requestPaint(); + // } + + // onPaint: { + // var ctx = getContext("2d"); + // ctx.clearRect(0, 0, width, height); + // if (smoothedData.length === 0) { + // return; + // } + + // var barWidth = width / root.numBands; + + // ctx.fillStyle = Colors.md3.on_primary; + // for (let i = 0; i < root.numBands; i++) { + // let normalized = (smoothedData[i] || 0) / inputMax; + // if (normalized > 1) + // normalized = 1; + // let barHeight = normalized * height; + + // ctx.fillRect(Math.floor(i * barWidth), Math.floor(height - barHeight), Math.ceil(barWidth), Math.floor(barHeight)); + // } + // } + // } + } + + // CavaService { + // id: cavaService + // onCavaDataChanged: data => { + // visualizer.updateData(data); + // } + // } +} diff --git a/quickshell/ui/TopBar.qml b/quickshell/ui/TopBar.qml index b8bc6c6..e81a7f4 100644 --- a/quickshell/ui/TopBar.qml +++ b/quickshell/ui/TopBar.qml @@ -44,6 +44,8 @@ Item { artist: root.nowPlayingArtist title: root.nowPlayingTitle artUrl: root.nowPlayingArtUrl + Layout.fillHeight: true + Layout.alignment: Qt.AlignBottom } // Spacer