bbidulock / icewm

A window manager designed for speed, usability, and consistency
Other
570 stars 97 forks source link

i need need help with icewm addon #748

Closed develperbayman closed 8 months ago

develperbayman commented 9 months ago

so im trying to use a custom volume control written in python im using debian running icewm works great so about a day ago i decided i needed something better for volume control so i rolled a python script i like it so i wrote a installer script for it but i cant seem to get the script to run the way i want the goal is to

1.create a menu entry

  1. have it start with icewm as a service?
  2. basically im trying to get a little icon on the right of the task bar to open and close the script

volume-install.py:

import os
import getpass

# Detect the path to the current script
current_script_path = os.path.abspath(__file__)

# Get the current user's home directory
user_home = os.path.expanduser("~")

# Set the path to your icon file
icon_path = os.path.join(user_home, "pyvolume", "volume.png")  # Assuming the icon is in the "pyvolume" folder

# Define the paths for the desktop entry and autostart script
desktop_entry_dir = os.path.join(user_home, ".config/autostart")
desktop_entry_path = os.path.join(desktop_entry_dir, "volume_control.desktop")

# Create the necessary directories if they don't exist
os.makedirs(desktop_entry_dir, exist_ok=True)

# Create a desktop entry file
desktop_entry = f"""[Desktop Entry]
Name=Volume Control
Exec=python3 {current_script_path}
Icon={icon_path}
Type=Application
StartupNotify=true
X-ICEWM-Taskbar-Icon=volume-control
"""

with open(desktop_entry_path, "w") as desktop_entry_file:
    desktop_entry_file.write(desktop_entry)

# Add an entry to IceWM autostart
autostart_script_path = os.path.join(user_home, ".icewm/autostart")

with open(autostart_script_path, "a") as autostart_script_file:
    autostart_script_file.write(f"/usr/bin/python3 {current_script_path} &\n")

# Restart IceWM (optional, you may need to log out and log back in)
os.system("pkill -x icewm")

print("Configuration completed. Your application will start at login with an icon in the taskbar.")

volume.py:

import sys
import os
import pulsectl
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QPainter, QBrush
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QSlider, QLabel, QPushButton, QComboBox

class VolumeControl(QWidget):
    def __init__(self):
        super().__init__()

        self.pulse = pulsectl.Pulse('volume-control')  # Create a PulseAudio context
        self.sinks = self.pulse.sink_list()  # Get a list of audio output sinks
        self.sources = self.pulse.source_list()  # Get a list of audio input sources

        self.selected_sink = self.sinks[0] if self.sinks else None
        self.selected_source = self.sources[0] if self.sources else None

        # Initialize attributes
        self.output_slider = None
        self.output_label = None
        self.input_slider = None
        self.input_label = None

        self.init_ui()

    def init_ui(self):
        # Configure the main window
        self.setWindowTitle('Volume Control')
        self.setGeometry(100, 100, 400, 300)
        self.setStyleSheet("background-color: #222;")

        # Create a layout
        layout = QVBoxLayout()

        # Output Sink Combo Box
        self.sink_combo = QComboBox()
        self.sink_combo.setStyleSheet("font-size: 14px; color: white;")
        self.sink_combo.currentIndexChanged.connect(self.select_sink)
        for sink in self.sinks:
            self.sink_combo.addItem(sink.description, sink)
        layout.addWidget(self.sink_combo)

        # Volume slider for the selected output sink
        self.output_slider = QSlider(Qt.Horizontal)
        self.output_slider.setRange(0, 100)
        self.output_slider.setValue(int(self.selected_sink.volume.value_flat * 100))
        self.output_slider.setStyleSheet(
            "QSlider::groove:horizontal { background-color: #444; height: 8px; border: none; }"
            "QSlider::handle:horizontal { background-color: gold; width: 16px; border: none; }"
        )
        self.output_slider.valueChanged.connect(self.set_output_volume)
        layout.addWidget(self.output_slider)

        # Volume label for the selected output sink
        self.output_label = QLabel(f'Volume: {self.selected_sink.volume.value_flat:.0%}')
        self.output_label.setAlignment(Qt.AlignCenter)
        self.output_label.setStyleSheet("color: gold; font-size: 16px;")
        layout.addWidget(self.output_label)

        # Input Source Combo Box
        self.source_combo = QComboBox()
        self.source_combo.setStyleSheet("font-size: 14px; color: white;")
        self.source_combo.currentIndexChanged.connect(self.select_source)
        for source in self.sources:
            self.source_combo.addItem(source.description, source)
        layout.addWidget(self.source_combo)

        # Volume slider for the selected input source
        self.input_slider = QSlider(Qt.Horizontal)
        self.input_slider.setRange(0, 100)
        self.input_slider.setValue(int(self.selected_source.volume.value_flat * 100))
        self.input_slider.setStyleSheet(
            "QSlider::groove:horizontal { background-color: #444; height: 8px; border: none; }"
            "QSlider::handle:horizontal { background-color: gold; width: 16px; border: none; }"
        )
        self.input_slider.valueChanged.connect(self.set_input_volume)
        layout.addWidget(self.input_slider)

        # Volume label for the selected input source
        self.input_label = QLabel(f'Volume: {self.selected_source.volume.value_flat:.0%}')
        self.input_label.setAlignment(Qt.AlignCenter)
        self.input_label.setStyleSheet("color: gold; font-size: 16px;")
        layout.addWidget(self.input_label)

        # Microphone input strength indicator (light)
        self.input_light = QLabel()
        self.input_light.setFixedSize(24, 24)
        self.input_light.setStyleSheet("background-color: red; border-radius: 12px;")
        layout.addWidget(self.input_light, alignment=Qt.AlignCenter)

        self.setLayout(layout)

    def select_sink(self, index):
        self.selected_sink = self.sinks[index]
        if self.output_slider:
            self.output_slider.setValue(int(self.selected_sink.volume.value_flat * 100))
        if self.output_label:
            self.output_label.setText(f'Volume: {self.selected_sink.volume.value_flat:.0%}')

    def set_output_volume(self, value):
        if self.selected_sink:
            # Calculate left and right channel volumes
            volume = min(max(0.0, value / 100.0), 1.0)
            self.pulse.volume_set_all_chans(self.selected_sink, volume)
            if self.output_label:
                self.output_label.setText(f'Volume: {volume:.0%}')

    def select_source(self, index):
        self.selected_source = self.sources[index]
        if self.input_slider:
            self.input_slider.setValue(int(self.selected_source.volume.value_flat * 100))
        if self.input_label:
            self.input_label.setText(f'Volume: {self.selected_source.volume.value_flat:.0%}')

    def set_input_volume(self, value):
        if self.selected_source:
            # Calculate left and right channel volumes
            volume = min(max(0.0, value / 100.0), 1.0)
            self.pulse.volume_set_all_chans(self.selected_source, volume)
            if self.input_label:
                self.input_label.setText(f'Volume: {volume:.0%}')

            # Update microphone input strength indicator (light)
            input_strength = int(volume * 255)
            self.input_light.setStyleSheet(f"background-color: rgb({255 - input_strength}, {input_strength}, 0);")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = VolumeControl()
    window.show()
    sys.exit(app.exec_())

im thinking about calling it pyvolume?

cheapy commented 9 months ago

How much memory does it use? I use a program called ps_mem.py to get a listing. I'm sure there are other ways to check.

Not to discourage creativity, but there is a package called volumeicon that takes 17 mb of memory to run that I think does this.

Another way to accomplish it would be with a YAD notification icon which would take about 11 mb of memory.

A third way of doing it that needs no memory except when its being used is too add an icon to the toolbar to call a program like yours, a YAD window, or other dialog program.

A fourth way to accomplish it on systems with multimedia keys is to program those keys to just work, and if you want the result to be displayed, a YAD window could be displayed.

I still wish IceWM would include an option for multiple generic tray icons, similar to the built-in Network monitor icons, my main reason for it to be included is that if it was built-in, it would use dramatically less memory than separate addons.

develperbayman commented 9 months ago

vramusage

27.7 mb ram i know i can trim that by half ....but i really liked the way it looks using qt5

develperbayman commented 9 months ago

oddly enough i didnt think to try hardware keys ...so i did and they work just dont provide and feedback on the volume level ....maybe a pointless exercise ....since i like to reinvent the wheel next ill try my had at a wallpaper switcher lol

cheapy commented 9 months ago

If you look at the keys file you might find it is running a program when you press the up, down, or mute keys. You could change what it runs to instead call a program like yours with a parameter telling it what action to take and displaying the result. It could run until you closed it or maybe exit on certain actions or a timeout, thus freeing up the memory at that point. I guess my point is that IceWM is a very light window manager , which can and is used by many older, low resource machines, and if you want them able to run your program, it needs to also conserve resources as well.

rubyFeedback commented 9 months ago

Don't forget to show the final version of the .py file too; I may have a try to port it into ruby (or an equivalent) one day, if it works. Extending icewm via "scripting" languages would be pretty great.

develperbayman commented 9 months ago

honestly ill prob not do any more with this for now i actually changed operating system for AI purpose however ...i do i have plans of a all python linux based operating system built for clustering featuring AI named "computer" ill probably implement this there