From 58c238f3b9ae6b5ee454b108d8fff8bb71f888fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20H=C3=BCbner?= Date: Tue, 14 Mar 2023 10:34:00 +0100 Subject: [PATCH] First example --- extension.js | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ metadata.json | 8 +++ stylesheet.css | 1 + 3 files changed, 155 insertions(+) create mode 100644 extension.js create mode 100644 metadata.json create mode 100644 stylesheet.css diff --git a/extension.js b/extension.js new file mode 100644 index 0000000..7671623 --- /dev/null +++ b/extension.js @@ -0,0 +1,146 @@ +/* extension.js + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* exported init */ + +const GETTEXT_DOMAIN = 'my-indicator-extension'; + +const { GObject, St } = imports.gi; +const GLib = imports.gi.GLib; +const ByteArray = imports.byteArray; + +const ExtensionUtils = imports.misc.extensionUtils; +const Main = imports.ui.main; +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; + +const _ = ExtensionUtils.gettext; + +const Indicator = GObject.registerClass( + class Indicator extends PanelMenu.Button { + _init() { + super._init(0.0, _('My Shiny Indicator')); + + this.add_child(new St.Icon({ + icon_name: 'face-smile-symbolic', + style_class: 'system-status-icon', + })); + + let sampleRate = getCurrentSampleRate(); + let currentSampleRate = new PopupMenu.PopupMenuItem(_("Sample Rate: " + sampleRate)); + this.menu.addMenuItem(currentSampleRate); + + let allowedRates = getAllowedSampleRates(); + + for (let i = 0; i < allowedRates.length; i++) { + let allowedRate = new PopupMenu.PopupMenuItem(_("Allowed Rates: " + allowedRates[i])); + allowedRate.connect('activate', () => { + console.log("set sample rate " + allowedRates[i]); + setSampleRate(allowedRates[i]); + currentSampleRate.label.text = "Sample Rate: " + getCurrentSampleRate(); + }); + + this.menu.addMenuItem(allowedRate); + } + } + }); + +class Extension { + constructor(uuid) { + this._uuid = uuid; + + ExtensionUtils.initTranslations(GETTEXT_DOMAIN); + } + + enable() { + this._indicator = new Indicator(); + Main.panel.addToStatusArea(this._uuid, this._indicator); + } + + disable() { + this._indicator.destroy(); + this._indicator = null; + } +} + +function init(meta) { + return new Extension(meta.uuid); +} + +function setSampleRate(sampleRate) { + spawnCommandLine("pw-metadata -n settings 0 clock.rate " + sampleRate); +} + +function getCurrentSampleRate() { + let res = spawnCommandLine("pw-metadata -n settings"); + let lines = res.split(/\r?\n/); + + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes('clock.rate')) { + let phrases = lines[i].split(" "); + + for (let j = 0; j < phrases.length; j++) { + if (phrases[j].includes("value")) { + return phrases[j].slice(7, -1); + } + } + } + } + + return "not found"; +} + +function getAllowedSampleRates() { + let res = spawnCommandLine("pw-metadata -n settings"); + let lines = res.split(/\r?\n/); + + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes('clock.allowed-rates')) { + let valueIndex = lines[i].indexOf("value"); + + if (valueIndex !== -1) { + return lines[i].slice(valueIndex + 9, -11).replaceAll(",", "").split(" "); + } + } + } + + return "not found"; +} + +// Runs @command_line in the background, handling any errors that +// occur when trying to parse or start the program. +function spawnCommandLine(command_line) { + try { + let [, stdout, stderr, status] = GLib.spawn_command_line_sync(command_line); + + if (status !== 0) { + if (stderr instanceof Uint8Array) + stderr = ByteArray.toString(stderr); + + throw new Error(stderr); + } + + if (stdout instanceof Uint8Array) + stdout = ByteArray.toString(stdout); + + // Now were done blocking the main loop, phewf! + return stdout; + } catch (e) { + throw new Error(e); + } +} diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..f99bb25 --- /dev/null +++ b/metadata.json @@ -0,0 +1,8 @@ +{ + "name": "Pipewire Settings", + "description": "Change pipewire settings for the current session", + "uuid": "pipewiresettings@gavania.de", + "shell-version": [ + "43" + ] +} diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 0000000..37b93f2 --- /dev/null +++ b/stylesheet.css @@ -0,0 +1 @@ +/* Add your custom extension styling here */