diff --git a/gui-apps/swaync/Manifest b/gui-apps/swaync/Manifest index 1957ad3a66..15b729c6d4 100644 --- a/gui-apps/swaync/Manifest +++ b/gui-apps/swaync/Manifest @@ -1,2 +1,3 @@ DIST swaync-0.7.3.tar.gz 3155355 BLAKE2B d976d908c12eef9a0fe71e269fd4dd1bca44cb7a389ea3b6fbcf7ef0a7cfd17623e4fa03fb61cb7d5a26837deafd0b3f8197774fe1ce17c47d512632d5aedc81 SHA512 fe049fae8ece0e54badd44ea6d04f7fa0a09c7cb258612897dbcb4b7b60ef28fc19113ec4b84520ac8226901b9d5a0b9cd11c3b071d9e90e840ac7e4595a51fc DIST swaync-0.8.0.tar.gz 3170861 BLAKE2B a43fd4d095b3bb1b39ff914cf3f09f9d97807d95365839a30c46c607c601c8e557e4365e3c23cbf650dca7b5a51523e4fbc8ecf49d7863b717b04e0c90e04f46 SHA512 c1ee542fff2b6b06cd0def99c96bede5cb3dc576ab4e0498bd110f1b6e3df2786526d5ec58dbfc7f5c488afc2c1c85541e878c76118486530b8937a5e13a0799 +DIST swaync-0.9.0.tar.gz 3178186 BLAKE2B 09c92e094da8c97384c78ac0afffc8caa968c78cad298056a99377da6a06e4cc496e0fbf469f0096d0378a7f78e0717e816dd8f43ef6a45270bd7b13f8f90d42 SHA512 1c9bb7908d74752cdb03b11d15794a18ca6360aec1a0d00897e252954544179885841905d0ba7464da8e29d0cdc8dc6b33b65296a7e61478ed160980b6f26b32 diff --git a/gui-apps/swaync/files/swaync-0.9.0-pulsefree.patch b/gui-apps/swaync/files/swaync-0.9.0-pulsefree.patch new file mode 100644 index 0000000000..20ea54a73d --- /dev/null +++ b/gui-apps/swaync/files/swaync-0.9.0-pulsefree.patch @@ -0,0 +1,1173 @@ +diff --git a/man/swaync.5.scd b/man/swaync.5.scd.2 +index 70fdd6e..7b4f638 100644 +--- a/man/swaync.5.scd ++++ b/man/swaync.5.scd.2 +@@ -405,54 +405,6 @@ config file to be able to detect config errors + description: "Command to be executed on click" ++ + description: A list of actions containing a label and a command ++ + description: A grid of buttons that execute shell commands ++ +- *volume*++ +- type: object ++ +- css class: ++ +- widget-volume ++ +- per-app-volume ++ +- properties: ++ +- label: ++ +- type: string ++ +- optional: true ++ +- default: "Volume" ++ +- description: Text displayed in front of the volume slider ++ +- show-per-app: ++ +- type: bool ++ +- optional: true ++ +- default: false ++ +- description: Show per app volume control ++ +- empty-list-label: ++ +- type: string ++ +- optional: true ++ +- default: "No active sink input" ++ +- description: Text displayed when there are not active sink inputs ++ +- expand-button-label: ++ +- type: string ++ +- optional: true ++ +- default: "⇧" ++ +- description: Label displayed on button to show per app volume control ++ +- collapse-button-label: ++ +- type: string ++ +- optional: true ++ +- default: "⇩" ++ +- description: Label displayed on button to hide per app volume control ++ +- icon-size: ++ +- type: integer ++ +- optional: true ++ +- default: 24 ++ +- description: Size of the application icon in per app volume control ++ +- animation-type: ++ +- type: string ++ +- optional: true ++ +- default: "slide_down" ++ +- description: Animation type for the per app volume control ++ +- enum: ["slide_down", "slide_up", "none"] ++ +- animation-duration: ++ +- type: integer ++ +- optional: true ++ +- default: 250 ++ +- description: Duration of animation in milliseconds ++ +- description: Slider to control pulse volume ++ + *backlight*++ + type: object ++ + css class: widget-backlight ++ +diff --git a/src/configSchema.json b/src/configSchema.json2 +index b54e247..2390951 100644 +--- a/src/configSchema.json ++++ b/src/configSchema.json2 +@@ -475,54 +475,6 @@ + } + } + }, +- "volume": { +- "type": "object", +- "description": "Slider to control pulse volume", +- "additionalProperties": false, +- "properties": { +- "label": { +- "type": "string", +- "description": "Text displayed in front of the volume slider", +- "default": "Volume" +- }, +- "show-per-app": { +- "type": "boolean", +- "default": false, +- "description": "Show per app volume control" +- }, +- "empty-list-label": { +- "type": "string", +- "default": "No active sink input", +- "description": "Text displayed when there are not active sink inputs" +- }, +- "expand-button-label": { +- "type": "string", +- "default": "⇧", +- "description": "Label displayed on button to show per app volume control" +- }, +- "collapse-button-label": { +- "type": "string", +- "default": "⇩", +- "description": "Label displayed on button to hide per app volume control" +- }, +- "icon-size": { +- "type": "integer", +- "default": 24, +- "description": "Size of the application icon in per app volume control" +- }, +- "animation-type": { +- "type": "string", +- "default": "slide_down", +- "description": "Animation type for menu", +- "enum": ["slide_down", "slide_up", "none"] +- }, +- "animation-duration":{ +- "type": "integer", +- "default": 250, +- "description": "Duration of animation in milliseconds" +- } +- } +- }, + "backlight": { + "type": "object", + "description": "Slider to control monitor brightness", +diff --git a/src/controlCenter/widgets/factory.vala b/src/controlCenter/widgets/factory.vala +index aea178d..f2ed445 100644 +--- a/src/controlCenter/widgets/factory.vala ++++ b/src/controlCenter/widgets/factory.vala +@@ -26,9 +26,6 @@ namespace SwayNotificationCenter.Widgets { + case "buttons-grid": + widget = new ButtonsGrid (suffix, swaync_daemon, noti_daemon); + break; +- case "volume": +- widget = new Volume (suffix, swaync_daemon, noti_daemon); +- break; + case "backlight": + widget = new Backlight (suffix, swaync_daemon, noti_daemon); + break; +diff --git a/src/controlCenter/widgets/volume/pulseDaemon.vala b/src/controlCenter/widgets/volume/pulseDaemon.vala.2 +index 7742e25..e69de29 100644 +--- a/src/controlCenter/widgets/volume/pulseDaemon.vala ++++ b/src/controlCenter/widgets/volume/pulseDaemon.vala.2 +@@ -1,647 +0,0 @@ +-// From SwaySettings PulseAudio page: https://github.com/ErikReider/SwaySettings/blob/407c9e99dd3e50a0f09c64d94a9e6ff741488378/src/Pages/Pulse/PulseDaemon.vala +-using PulseAudio; +-using Gee; +- +-namespace SwayNotificationCenter.Widgets { +- /** +- * Loosely based off of Elementary OS switchboard-plug-sound +- * https://github.com/elementary/switchboard-plug-sound +- */ +- public class PulseDaemon : Object { +- private Context ? context; +- private GLibMainLoop mainloop; +- private bool quitting = false; +- +- public bool running { get; private set; } +- +- private string default_sink_name { get; private set; } +- private string default_source_name { get; private set; } +- +- private PulseDevice ? default_sink = null; +- +- public HashMap sinks { get; private set; } +- +- public HashMap active_sinks { get; private set; } +- +- construct { +- mainloop = new GLibMainLoop (); +- +- sinks = new HashMap (); +- +- active_sinks = new HashMap (); +- } +- +- public void start () { +- get_context (); +- } +- +- public void close () { +- quitting = true; +- if (this.context != null) { +- context.disconnect (); +- context = null; +- } +- } +- +- ~PulseDaemon () { +- this.close (); +- } +- +- public signal void change_default_device (PulseDevice device); +- +- public signal void new_active_sink (PulseSinkInput device); +- public signal void change_active_sink (PulseSinkInput device); +- public signal void remove_active_sink (PulseSinkInput device); +- +- public signal void new_device (PulseDevice device); +- public signal void change_device (PulseDevice device); +- public signal void remove_device (PulseDevice device); +- +- private void get_context () { +- var ctx = new Context (mainloop.get_api (), null); +- ctx.set_state_callback ((ctx) => { +- debug ("Pulse Status: %s\n", ctx.get_state ().to_string ()); +- switch (ctx.get_state ()) { +- case Context.State.CONNECTING: +- case Context.State.AUTHORIZING: +- case Context.State.SETTING_NAME: +- break; +- case Context.State.READY: +- ctx.set_subscribe_callback (subscription); +- ctx.subscribe (Context.SubscriptionMask.SINK_INPUT | +- Context.SubscriptionMask.SINK | +- Context.SubscriptionMask.CARD | +- Context.SubscriptionMask.SERVER); +- // Init data +- ctx.get_server_info (this.get_server_info); +- running = true; +- break; +- case Context.State.TERMINATED: +- case Context.State.FAILED: +- running = false; +- if (quitting) { +- quitting = false; +- break; +- } +- stderr.printf ( +- "PulseAudio connection lost. Will retry connection.\n"); +- get_context (); +- break; +- default: +- running = false; +- stderr.printf ("Connection failure: %s\n", +- PulseAudio.strerror (ctx.errno ())); +- break; +- } +- }); +- if (ctx.connect ( +- null, Context.Flags.NOFAIL, null) < 0) { +- stdout.printf ("pa_context_connect() failed: %s\n", +- PulseAudio.strerror (ctx.errno ())); +- } +- this.context = ctx; +- } +- +- private void subscription (Context ctx, +- Context.SubscriptionEventType t, +- uint32 index) { +- var type = t & Context.SubscriptionEventType.FACILITY_MASK; +- var event = t & Context.SubscriptionEventType.TYPE_MASK; +- switch (type) { +- case Context.SubscriptionEventType.SINK_INPUT: +- switch (event) { +- default: break; +- case Context.SubscriptionEventType.NEW: +- case Context.SubscriptionEventType.CHANGE: +- ctx.get_sink_input_info_list (this.get_sink_input_info); +- break; +- case Context.SubscriptionEventType.REMOVE: +- // A safe way of removing the sink_input +- var iter = active_sinks.map_iterator (); +- while (iter.next ()) { +- var sink_input = iter.get_value (); +- if (sink_input.index != index) continue; +- this.remove_active_sink (sink_input); +- iter.unset (); +- break; +- } +- break; +- } +- break; +- case Context.SubscriptionEventType.SINK: +- switch (event) { +- default: break; +- case Context.SubscriptionEventType.NEW: +- case Context.SubscriptionEventType.CHANGE: +- ctx.get_sink_info_by_index (index, this.get_sink_info); +- break; +- case Context.SubscriptionEventType.REMOVE: +- foreach (var sink in sinks.values) { +- if (sink.device_index != index) continue; +- sink.removed = true; +- sink.is_default = false; +- this.remove_device (sink); +- break; +- } +- break; +- } +- break; +- case Context.SubscriptionEventType.CARD: +- switch (event) { +- default: break; +- case Context.SubscriptionEventType.NEW: +- case Context.SubscriptionEventType.CHANGE: +- ctx.get_card_info_by_index (index, this.get_card_info); +- break; +- case Context.SubscriptionEventType.REMOVE: +- // A safe way of removing the sink_input +- var iter = sinks.map_iterator (); +- while (iter.next ()) { +- var device = iter.get_value (); +- if (device.card_index != index) continue; +- device.removed = true; +- device.is_default = false; +- iter.unset (); +- this.remove_device (device); +- break; +- } +- break; +- } +- break; +- case Context.SubscriptionEventType.SERVER: +- ctx.get_server_info (this.get_server_info); +- break; +- default: break; +- } +- } +- +- /* +- * Getters +- */ +- +- /** +- * Gets called when any server value changes like default devices +- * Calls `get_card_info_list` and `get_sink_info_list` +- */ +- private void get_server_info (Context ctx, ServerInfo ? info) { +- if (this.default_sink_name == null) { +- this.default_sink_name = info.default_sink_name; +- } +- if (this.default_sink_name != info.default_sink_name) { +- this.default_sink_name = info.default_sink_name; +- } +- +- ctx.get_card_info_list (this.get_card_info); +- ctx.get_sink_info_list (this.get_sink_info); +- +- foreach (var sink_input in active_sinks) { +- sink_input.value.active = false; +- } +- ctx.get_sink_input_info_list (this.get_sink_input_info); +- var iter = active_sinks.map_iterator (); +- while (iter.next ()) { +- var sink_input = iter.get_value (); +- if (!sink_input.active) { +- this.remove_active_sink (sink_input); +- iter.unset (); +- } +- } +- } +- +- private void get_sink_input_info (Context ctx, SinkInputInfo ? info, int eol) { +- if (info == null || eol != 0) return; +- +- uint32 id = PulseSinkInput.get_hash_map_key (info.index); +- PulseSinkInput sink_input = null; +- bool has_sink_input = active_sinks.has_key (id); +- if (has_sink_input) { +- sink_input = active_sinks.get (id); +- } else { +- sink_input = new PulseSinkInput (); +- } +- +- sink_input.index = info.index; +- sink_input.sink_index = info.sink; +- sink_input.client_index = info.client; +- +- sink_input.name = info.proplist.gets ("application.name"); +- sink_input.application_binary = info.proplist +- .gets ("application.process.binary"); +- sink_input.application_icon_name = info.proplist +- .gets ("application.icon_name"); +- sink_input.media_name = info.proplist.gets ("media.name"); +- +- sink_input.is_muted = info.mute == 1; +- +- sink_input.cvolume = info.volume; +- sink_input.channel_map = info.channel_map; +- sink_input.balance = sink_input.cvolume +- .get_balance (sink_input.channel_map); +- sink_input.volume_operations.foreach ((op) => { +- if (op.get_state () != Operation.State.RUNNING) { +- sink_input.volume_operations.remove (op); +- } +- return Source.CONTINUE; +- }); +- if (sink_input.volume_operations.is_empty) { +- sink_input.volume = volume_to_double ( +- sink_input.cvolume.max ()); +- } +- sink_input.active = true; +- +- if (!has_sink_input) { +- active_sinks.set (id, sink_input); +- this.new_active_sink (sink_input); +- } else { +- this.change_active_sink (sink_input); +- } +- } +- +- private void get_card_info (Context ctx, CardInfo ? info, int eol) { +- if (info == null || eol != 0) return; +- +- unowned string ? description = info.proplist +- .gets ("device.description"); +- unowned string ? props_icon = info.proplist +- .gets ("device.icon_name"); +- +- PulseDevice[] ports = {}; +- foreach (var port in info.ports) { +- if (port->available == PortAvailable.NO) continue; +- +- bool is_input = port->direction == Direction.INPUT; +- HashMap devices = this.sinks; +- string id = PulseDevice.get_hash_map_key ( +- description, port.name); +- +- bool has_device = devices.has_key (id); +- PulseDevice device = has_device +- ? devices.get (id) : new PulseDevice (); +- bool device_is_removed = device.removed; +- device.removed = false; +- +- device.is_bluetooth = info.proplist.gets ("device.api") == "bluez5"; +- +- device.card_index = info.index; +- device.direction = port.direction; +- +- device.card_name = info.name; +- device.card_description = description; +- device.card_active_profile = info.active_profile2->name; +- +- device.port_name = port.name; +- device.port_description = port.description; +- device.port_id = port->proplist.gets ("card.profile.port"); +- +- // Get port profiles2 (profiles is "Superseded by profiles2") +- // and sort largest priority first +- var profiles = new ArrayList +- .wrap (port->profiles2); +- +- profiles.sort ((a, b) => { +- if (a->priority == b->priority) return 0; +- return a.priority > b.priority ? -1 : 1; +- }); +- string[] new_profiles = {}; +- Array pulse_profiles = new Array (); +- foreach (var profile in profiles) { +- new_profiles += profile->name; +- +- var card_profile = new PulseCardProfile (profile); +- pulse_profiles.append_val (card_profile); +- if (profile->name == device.card_active_profile) { +- device.active_profile = card_profile; +- } +- } +- device.port_profiles = new_profiles; +- device.profiles = pulse_profiles; +- +- device.icon_name = port->proplist.gets ("device.icon_name") +- ?? props_icon; +- if (device.icon_name == null) { +- device.icon_name = is_input +- ? "microphone-sensitivity-high" +- : "audio-speakers"; +- } +- devices.set (id, device); +- ports += device; +- if (!has_device || device_is_removed) { +- this.new_device (device); +- } +- } +- +- /** Removes ports that are no longer available */ +- var iter = sinks.map_iterator (); +- while (iter.next ()) { +- var device = iter.get_value (); +- if (device.card_index != info.index) continue; +- bool found = false; +- foreach (var p in ports) { +- if (device.get_current_hash_key () +- == p.get_current_hash_key ()) { +- found = true; +- break; +- } +- } +- if (!found) { +- iter.unset (); +- remove_device (device); +- break; +- } +- } +- } +- +- private void get_sink_info (Context ctx, SinkInfo ? info, int eol) { +- if (info == null || eol != 0) return; +- +- bool found = false; +- foreach (PulseDevice device in sinks.values) { +- if (device.card_index == info.card) { +- // Sets the name and index to profiles that aren't active +- // Ex: The HDMI audio port that's not active +- device.device_name = info.name; +- device.device_description = info.description; +- device.device_index = info.index; +- // If the current selected sink profile is this +- if (info.active_port != null +- && info.active_port->name == device.port_name) { +- found = true; +- +- device.card_sink_port_name = info.active_port->name; +- bool is_default = +- device.device_name == this.default_sink_name; +- device.is_default = is_default; +- +- device.is_muted = info.mute == 1; +- +- device.is_virtual = info.proplist.gets ("node.virtual") == "true"; +- +- device.cvolume = info.volume; +- device.channel_map = info.channel_map; +- device.balance = device.cvolume +- .get_balance (device.channel_map); +- device.volume_operations.foreach ((op) => { +- if (op.get_state () != Operation.State.RUNNING) { +- device.volume_operations.remove (op); +- } +- return Source.CONTINUE; +- }); +- if (device.volume_operations.is_empty) { +- device.volume = volume_to_double ( +- device.cvolume.max ()); +- } +- +- if (is_default) { +- this.default_sink = device; +- this.change_default_device (device); +- } +- } +- this.change_device (device); +- } +- } +- // If not found, it's a cardless device +- if (found) return; +- +- HashMap devices = this.sinks; +- string id = PulseDevice.get_hash_map_key ( +- info.index.to_string (), info.description); +- bool has_device = devices.has_key (id); +- PulseDevice device = has_device ? devices.get (id) : new PulseDevice (); +- +- bool device_is_removed = device.removed; +- device.removed = false; +- +- device.has_card = false; +- +- device.direction = PulseAudio.Direction.OUTPUT; +- +- device.device_name = info.name; +- device.device_description = info.description; +- device.device_index = info.index; +- +- bool is_default = device.device_name == this.default_source_name; +- device.is_default = is_default; +- +- device.is_muted = info.mute == 1; +- +- device.is_virtual = info.proplist.gets ("node.virtual") == "true"; +- +- device.icon_name = "application-x-executable-symbolic"; +- +- device.cvolume = info.volume; +- device.channel_map = info.channel_map; +- device.balance = device.cvolume +- .get_balance (device.channel_map); +- device.volume_operations.foreach ((op) => { +- if (op.get_state () != Operation.State.RUNNING) { +- device.volume_operations.remove (op); +- } +- return Source.CONTINUE; +- }); +- if (device.volume_operations.is_empty) { +- device.volume = volume_to_double ( +- device.cvolume.max ()); +- } +- +- devices.set (id, device); +- +- if (is_default) { +- this.default_sink = device; +- this.change_default_device (device); +- } +- if (!has_device || device_is_removed) { +- this.new_device (device); +- } +- this.change_device (device); +- } +- +- /* +- * Setters +- */ +- public void set_sink_input_volume (PulseSinkInput sink_input, double volume) { +- sink_input.volume_operations.foreach ((operation) => { +- if (operation.get_state () == Operation.State.RUNNING) { +- operation.cancel (); +- } +- +- sink_input.volume_operations.remove (operation); +- return GLib.Source.CONTINUE; +- }); +- +- var cvol = sink_input.cvolume; +- cvol.scale (double_to_volume (volume)); +- Operation ? operation = null; +- operation = context.set_sink_input_volume ( +- sink_input.index, cvol); +- if (operation != null) { +- sink_input.volume_operations.add (operation); +- } +- } +- +- public void set_device_volume (PulseDevice device, double volume) { +- device.volume_operations.foreach ((operation) => { +- if (operation.get_state () == Operation.State.RUNNING) { +- operation.cancel (); +- } +- +- device.volume_operations.remove (operation); +- return GLib.Source.CONTINUE; +- }); +- +- var cvol = device.cvolume; +- cvol.scale (double_to_volume (volume)); +- Operation ? operation = null; +- if (device.direction == Direction.OUTPUT) { +- operation = context.set_sink_volume_by_name ( +- device.device_name, cvol); +- } +- +- if (operation != null) { +- device.volume_operations.add (operation); +- } +- } +- +- public async void set_default_device (PulseDevice device) { +- if (device == null) return; +- bool is_input = device.direction == Direction.INPUT; +- +- // Only set port and card profile if the device is attached to a card +- if (device.has_card) { +- // Gets the profile that includes support for your other device +- string profile_name = device.port_profiles[0]; +- PulseDevice alt_device = default_sink; +- if (alt_device != null) { +- foreach (var profile in device.port_profiles) { +- if (profile in alt_device.port_profiles) { +- profile_name = profile; +- break; +- } +- } +- } +- +- if (profile_name != device.card_active_profile) { +- yield set_card_profile_by_index (profile_name, device); +- yield wait_for_update (device, "device-name"); +- } +- +- if (!is_input) { +- if (device.port_name != device.card_sink_port_name) { +- debug ("Setting port to: %s", device.port_name); +- yield set_sink_port_by_name (device); +- } +- } +- +- if (device.device_name == null) { +- yield wait_for_update (device, "device-name"); +- } +- } +- +- if (!is_input) { +- if (device.device_name != default_sink_name) { +- debug ("Setting default sink to: %s", device.device_name); +- yield set_default_sink (device); +- } +- } +- } +- +- private async void wait_for_update (PulseDevice device, +- string prop_name) { +- SourceFunc callback = wait_for_update.callback; +- ulong handler_id = 0; +- handler_id = device.notify[prop_name].connect ((s, p) => { +- T prop_value; +- device.get (prop_name, out prop_value); +- if (prop_value != null) { +- device.disconnect (handler_id); +- Idle.add ((owned) callback); +- } +- }); +- yield; +- } +- +- public async void set_bluetooth_card_profile (PulseCardProfile profile, +- PulseDevice device) { +- context.set_card_profile_by_index (device.card_index, +- profile.name, +- (c, success) => { +- if (success == 1) { +- set_bluetooth_card_profile.callback (); +- } else { +- stderr.printf ("setting the card %s profile to %s failed\n", +- device.card_name, profile.name); +- } +- }); +- yield; +- // Wait until the device has been updated +- yield wait_for_update (device, "device-name"); +- } +- +- private async void set_card_profile_by_index (string profile_name, +- PulseDevice device) { +- context.set_card_profile_by_index (device.card_index, +- profile_name, +- (c, success) => { +- if (success == 1) { +- set_card_profile_by_index.callback (); +- } else { +- stderr.printf ("setting the card %s profile to %s failed\n", +- device.card_name, profile_name); +- } +- }); +- yield; +- } +- +- private async void set_sink_port_by_name (PulseDevice device) { +- context.set_sink_port_by_name (device.device_name, +- device.port_name, +- (c, success) => { +- if (success == 1) { +- set_sink_port_by_name.callback (); +- } else { +- stderr.printf ("setting sink port to %s failed\n", +- device.port_name); +- } +- }); +- yield; +- } +- +- private async void set_default_sink (PulseDevice device) { +- context.set_default_sink (device.device_name, (c, success) => { +- if (success == 1) { +- set_default_sink.callback (); +- } else { +- stderr.printf ("setting default sink to %s failed\n", +- device.device_name); +- } +- }); +- yield; +- } +- +- public void set_device_mute (bool state, PulseDevice device) { +- if (device.is_muted == state) return; +- if (device.direction == Direction.OUTPUT) { +- context.set_sink_mute_by_index ( +- device.device_index, state); +- } +- } +- +- public void set_sink_input_mute (bool state, PulseSinkInput sink_input) { +- if (sink_input.is_muted == state) return; +- context.set_sink_input_mute (sink_input.index, state); +- } +- +- /* +- * Volume utils +- */ +- +- private static double volume_to_double (PulseAudio.Volume vol) { +- double tmp = (double) (vol - PulseAudio.Volume.MUTED); +- return 100 * tmp / (double) (PulseAudio.Volume.NORM - PulseAudio.Volume.MUTED); +- } +- +- private static PulseAudio.Volume double_to_volume (double vol) { +- double tmp = (double) (PulseAudio.Volume.NORM - PulseAudio.Volume.MUTED) * vol / 100; +- return (PulseAudio.Volume) tmp + PulseAudio.Volume.MUTED; +- } +- } +-} +diff --git a/src/controlCenter/widgets/volume/pulseDevice.vala b/src/controlCenter/widgets/volume/pulseDevice.vala +deleted file mode 100644 +index accb8dc..0000000 +--- a/src/controlCenter/widgets/volume/pulseDevice.vala ++++ /dev/null +@@ -1,135 +0,0 @@ +-// From SwaySettings PulseAudio page: https://github.com/ErikReider/SwaySettings/blob/407c9e99dd3e50a0f09c64d94a9e6ff741488378/src/Pages/Pulse/PulseDevice.vala +-using PulseAudio; +-using Gee; +- +-namespace SwayNotificationCenter.Widgets { +- public class PulseCardProfile : Object { +- public string name; +- public string description; +- public uint32 n_sinks; +- public uint32 priority; +- int available; +- +- public PulseCardProfile (CardProfileInfo2 * profile) { +- this.name = profile->name; +- this.description = profile->description; +- this.n_sinks = profile->n_sinks; +- this.priority = profile->priority; +- this.available = profile->available; +- } +- +- public bool cmp (PulseCardProfile profile) { +- return profile.name == name +- && profile.description == description +- && profile.n_sinks == n_sinks +- && profile.priority == priority +- && profile.available == available; +- } +- } +- +- public class PulseDevice : Object { +- +- public bool removed { get; set; default = false; } +- +- public bool has_card { get; set; default = true; } +- +- /** The card index: ex. `Card #49` */ +- public uint32 card_index { get; set; } +- /** Sink index: ex. `Sink #55` */ +- public uint32 device_index { get; set; } +- +- /** Input or Output */ +- public Direction direction { get; set; } +- +- /** Is default Sink */ +- public bool is_default { get; set; } +- /** If the device is virtual */ +- public bool is_virtual { get; set; default = false; } +- /** If the device is a bluetooth device */ +- public bool is_bluetooth { get; set; default = false; } +- +- /** The icon name: `device.icon_name` */ +- public string icon_name { get; set; } +- +- /** The card name: `Name` */ +- public string card_name { get; set; } +- /** The card description: `device.description` */ +- public string card_description { get; set; } +- /** The card active profile: `Active Profile` */ +- public string card_active_profile { get; set; } +- /** The card sink port name: `Active Port` */ +- public string card_sink_port_name { get; set; } +- +- /** The Sink name: `Name` */ +- public string ? device_name { get; set; } +- /** The Sink description: `Description` */ +- public string device_description { get; set; } +- /** If the Sink is muted: `Mute` */ +- public bool is_muted { get; set; } +- +- public double volume { get; set; } +- public float balance { get; set; default = 0; } +- public CVolume cvolume; +- public ChannelMap channel_map; +- public LinkedList volume_operations { get; set; } +- +- /** Gets the name to be shown to the user: +- * "port_description - card_description" +- */ +- public string ? get_display_name () { +- if (card_name == null) { +- return device_description; +- } +- string p_desc = port_description; +- string c_desc = card_description; +- return "%s - %s".printf (p_desc, c_desc); +- } +- +- /** Compares PulseDevices. Returns true if they're the same */ +- public bool cmp (PulseDevice device) { +- return device.card_index == card_index +- && device.device_index == device_index +- && device.device_name == device_name +- && device.device_description == device_description +- && device.is_default == is_default +- && device.removed == removed +- && device.card_active_profile == card_active_profile +- && device.port_name == port_name; +- } +- +- /** +- * Gets the name to be shown to the user: +- * If has card: "card_description:port_name" +- * If cardless: "device_index:device_description" +- */ +- public string get_current_hash_key () { +- if (card_name == null) { +- return get_hash_map_key (device_index.to_string (), +- device_description); +- } +- return get_hash_map_key (card_description, port_name); +- } +- +- /** Gets the name to be shown to the user: +- * "card_description:port_name" +- */ +- public static string get_hash_map_key (string c_desc, string p_name) { +- return string.joinv (":", new string[] { c_desc, p_name }); +- } +- +- /** The port name: `Name` */ +- public string port_name { get; set; } +- /** The port name: `Description` */ +- public string port_description { get; set; } +- /** The port name: `card.profile.port` */ +- public string port_id { get; set; } +- /** All port profiles */ +- public string[] port_profiles { get; set; } +- public Array profiles { get; set; } +- public PulseCardProfile ? active_profile { get; set; } +- +- construct { +- volume_operations = new LinkedList (); +- } +- } +-} +diff --git a/src/controlCenter/widgets/volume/volume.vala b/src/controlCenter/widgets/volume/volume.vala.2 +index 5830602..e69de29 100644 +--- a/src/controlCenter/widgets/volume/volume.vala ++++ b/src/controlCenter/widgets/volume/volume.vala.2 +@@ -1,185 +0,0 @@ +-namespace SwayNotificationCenter.Widgets { +- public class Volume : BaseWidget { +- public override string widget_name { +- get { +- return "volume"; +- } +- } +- +- Gtk.Box main_volume_slider_container = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); +- Gtk.Label label_widget = new Gtk.Label (null); +- Gtk.Scale slider = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1); +- +- // Per app volume controll +- Gtk.ListBox levels_listbox; +- Gtk.Button reveal_button; +- Gtk.Revealer revealer; +- Gtk.Label no_sink_inputs_label; +- string empty_label = "No active sink input"; +- +- string expand_label = "⇧"; +- string collapse_label = "⇩"; +- int icon_size = 24; +- +- Gtk.RevealerTransitionType revealer_type = Gtk.RevealerTransitionType.SLIDE_DOWN; +- int revealer_duration = 250; +- +- private PulseDevice ? default_sink = null; +- private PulseDaemon client = new PulseDaemon (); +- +- private bool show_per_app; +- +- construct { +- this.client.change_default_device.connect (default_device_changed); +- +- slider.value_changed.connect (() => { +- if (default_sink != null) { +- this.client.set_device_volume ( +- default_sink, +- (float) slider.get_value ()); +- slider.tooltip_text = ((int) slider.get_value ()).to_string (); +- } +- }); +- } +- +- public Volume (string suffix, SwayncDaemon swaync_daemon, NotiDaemon noti_daemon) { +- base (suffix, swaync_daemon, noti_daemon); +- +- Json.Object ? config = get_config (this); +- if (config != null) { +- string ? label = get_prop (config, "label"); +- label_widget.set_label (label ?? "Volume"); +- +- show_per_app = get_prop (config, "show-per-app") ? true : false; +- +- string ? el = get_prop (config, "empty-list-label"); +- if (el != null) empty_label = el; +- +- string ? l1 = get_prop (config, "expand-button-label"); +- if (l1 != null) expand_label = l1; +- string ? l2 = get_prop (config, "collapse-button-label"); +- if (l2 != null) collapse_label = l2; +- +- int i = int.max (get_prop (config, "icon-size"), 0); +- if (i != 0) icon_size = i; +- +- revealer_duration = int.max (0, get_prop (config, "animation-duration")); +- if (revealer_duration == 0) revealer_duration = 250; +- +- string ? animation_type = get_prop (config, "animation-type"); +- if (animation_type != null) { +- switch (animation_type) { +- default: +- case "none": +- revealer_type = Gtk.RevealerTransitionType.NONE; +- break; +- case "slide_up": +- revealer_type = Gtk.RevealerTransitionType.SLIDE_UP; +- break; +- case "slide_down": +- revealer_type = Gtk.RevealerTransitionType.SLIDE_DOWN; +- break; +- } +- } +- } +- +- this.orientation = Gtk.Orientation.VERTICAL; +- +- slider.draw_value = false; +- +- main_volume_slider_container.add (label_widget); +- main_volume_slider_container.pack_start (slider, true, true, 0); +- add (main_volume_slider_container); +- +- if (show_per_app) { +- reveal_button = new Gtk.Button.with_label (expand_label); +- revealer = new Gtk.Revealer (); +- revealer.transition_type = revealer_type; +- revealer.transition_duration = revealer_duration; +- levels_listbox = new Gtk.ListBox (); +- levels_listbox.get_style_context ().add_class ("per-app-volume"); +- revealer.add (levels_listbox); +- +- if (this.client.active_sinks.size == 0) { +- no_sink_inputs_label = new Gtk.Label (empty_label); +- levels_listbox.add (no_sink_inputs_label); +- } +- +- foreach (var item in this.client.active_sinks.values) { +- levels_listbox.add (new SinkInputRow (item, client, icon_size)); +- } +- +- this.client.change_active_sink.connect (active_sink_change); +- this.client.new_active_sink.connect (active_sink_added); +- this.client.remove_active_sink.connect (active_sink_removed); +- +- reveal_button.clicked.connect (() => { +- bool show = revealer.reveal_child; +- revealer.set_reveal_child (!show); +- if (show) { +- reveal_button.label = expand_label; +- } else { +- reveal_button.label = collapse_label; +- } +- }); +- +- main_volume_slider_container.pack_end (reveal_button, false, false, 0); +- add (revealer); +- } +- +- show_all (); +- } +- +- public override void on_cc_visibility_change (bool val) { +- if (val) { +- this.client.start (); +- } else { +- this.client.close (); +- if (show_per_app) revealer.set_reveal_child (false); +- } +- } +- +- private void default_device_changed (PulseDevice device) { +- if (device != null && device.direction == PulseAudio.Direction.OUTPUT) { +- this.default_sink = device; +- slider.set_value (device.volume); +- } +- } +- +- private void active_sink_change (PulseSinkInput sink) { +- foreach (var row in levels_listbox.get_children ()) { +- if (row == null) continue; +- var s = (SinkInputRow) row; +- if (s.sink_input.cmp (sink)) { +- s.update (sink); +- break; +- } +- } +- } +- +- private void active_sink_added (PulseSinkInput sink) { +- // one element added -> remove the empty label +- if (this.client.active_sinks.size == 1) { +- var label = levels_listbox.get_children ().first ().data; +- levels_listbox.remove ((Gtk.Widget) label); +- } +- levels_listbox.add (new SinkInputRow (sink, client, icon_size)); +- show_all (); +- } +- +- private void active_sink_removed (PulseSinkInput sink) { +- foreach (var row in levels_listbox.get_children ()) { +- if (row == null) continue; +- var s = (SinkInputRow) row; +- if (s.sink_input.cmp (sink)) { +- levels_listbox.remove (row); +- break; +- } +- } +- if (levels_listbox.get_children ().length () == 0) { +- levels_listbox.add (no_sink_inputs_label); +- show_all (); +- } +- } +- } +-} +diff --git a/src/meson.build b/src/meson.build2 +index 78ce9f1..1ca63a3 100644 +--- a/src/meson.build ++++ b/src/meson.build2 +@@ -40,12 +40,6 @@ widget_sources = [ + 'controlCenter/widgets/menubar/menubar.vala', + # Widget: Buttons Grid + 'controlCenter/widgets/buttonsGrid/buttonsGrid.vala', +- # Widget: Volume +- 'controlCenter/widgets/volume/volume.vala', +- 'controlCenter/widgets/volume/pulseDaemon.vala', +- 'controlCenter/widgets/volume/pulseDevice.vala', +- 'controlCenter/widgets/volume/pulseSinkInput.vala', +- 'controlCenter/widgets/volume/sinkInputRow.vala', + # Widget: Backlight Slider + 'controlCenter/widgets/backlight/backlight.vala', + 'controlCenter/widgets/backlight/backlightUtil.vala', +@@ -79,8 +73,6 @@ app_deps = [ + meson.get_compiler('c').find_library('m', required : true), + meson.get_compiler('vala').find_library('posix'), + dependency('gee-0.8'), +- dependency('libpulse'), +- dependency('libpulse-mainloop-glib'), + ] + + # Checks if the user wants scripting enabled +diff --git a/src/style.css b/src/style2.css +index c9e93b3..e8fc5d6 100644 +--- a/src/style.css ++++ b/src/style2.css +@@ -313,27 +313,6 @@ + background: transparent; + } + +-/* Volume widget */ +- +-.widget-volume { +- background-color: @noti-bg; +- padding: 8px; +- margin: 8px; +- border-radius: 12px; +-} +- +-.widget-volume>box>button { +- background: transparent; +- border: none; +-} +- +-.per-app-volume { +- background-color: @noti-bg-alt; +- padding: 4px 8px 8px 8px; +- margin: 0px 8px 8px 8px; +- border-radius: 12px +-} +- + /* Backlight widget */ + .widget-backlight { + background-color: @noti-bg; \ No newline at end of file diff --git a/gui-apps/swaync/swaync-0.9.0.ebuild b/gui-apps/swaync/swaync-0.9.0.ebuild new file mode 100644 index 0000000000..55a4e04c20 --- /dev/null +++ b/gui-apps/swaync/swaync-0.9.0.ebuild @@ -0,0 +1,52 @@ +# Copyright 2022-2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit meson vala gnome2-utils + +MY_PN="SwayNotificationCenter" +DESCRIPTION="A simple notification daemon with a GTK gui for notifications and control center" +HOMEPAGE="https://github.com/ErikReider/SwayNotificationCenter" +SRC_URI="https://github.com/ErikReider/${MY_PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz" +S="${WORKDIR}/${MY_PN}-${PV}" + +LICENSE="GPL-3" +SLOT="0" +KEYWORDS="~amd64 ~x86" +IUSE="pulseaudio" + +DEPEND=" + dev-libs/libgee + dev-libs/glib:2 + dev-libs/gobject-introspection + dev-libs/json-glib + pulseaudio? ( + media-libs/libpulse + ) + dev-libs/wayland + >=gui-libs/gtk-layer-shell-0.7.0[introspection] + gui-libs/libhandy:1 + sys-apps/dbus + x11-libs/gdk-pixbuf:2 + x11-libs/gtk+:3 +" +RDEPEND="${DEPEND}" +BDEPEND=" + $(vala_depend) + app-text/scdoc +" + +src_prepare() { + ! use pulseaudio && local PATCHES=( "${FILESDIR}"/${P}-pulsefree.patch ) + default + vala_setup +} + +pkg_postinst() { + gnome2_schemas_update +} + +pkg_postrm() { + gnome2_schemas_update +}