4 // Advanced Volume Mixer
5 // Control programs' volume from gnome volume mixer applet.
7 // Author: Harry Karvonen <harry.karvonen@gmail.com>
10 const Clutter = imports.gi.Clutter;
11 const Lang = imports.lang;
12 const Gvc = imports.gi.Gvc;
13 const St = imports.gi.St;
15 const Main = imports.ui.main;
16 const PopupMenu = imports.ui.popupMenu;
18 const Volume = imports.ui.status.volume;
20 const AVM = imports.misc.extensionUtils.getCurrentExtension();
21 const Widget = AVM.imports.widget;
22 const Settings = AVM.imports.settings;
23 const Panel = AVM.imports.panel;
25 const AdvancedVolumeMixer = new Lang.Class({
26 Name: "AdvancedVolumeMixer",
27 Extends: PopupMenu.PopupMenuSection,
32 this.hasHeadphones = false;
34 this._control = Volume.getMixerControl();
37 this._settings = Settings.gsettings;
39 log("AdvVolumeMixer init");
40 log(this._control.get_vol_max_norm());
41 log(this._settings.get_enum("position"));
43 this._control.connect(
45 Lang.bind(this, this._onControlStateChanged)
47 this._control.connect(
48 "default-sink-changed",
49 Lang.bind(this, this._readOutput));
50 this._control.connect(
51 "default-source-changed",
52 Lang.bind(this, this._readInput)
54 this._control.connect(
56 Lang.bind(this, this._streamAdded)
58 this._control.connect(
60 Lang.bind(this, this._streamRemoved)
65 if (this._settings.get_enum("output-type") == 0) {
66 this._output = new Volume.OutputStreamSlider(this._control);
68 this._output = new Widget.AppOutputStreamSlider(this._control);
70 this._output.connect('stream-updated', Lang.bind(this, function() {
71 this.emit('icon-changed');
74 this._input = new Volume.InputStreamSlider(this._control);
75 this._separator = new PopupMenu.PopupSeparatorMenuItem();
77 this.addMenuItem(this._output.item);
78 this.addMenuItem(this._input.item);
79 this.addMenuItem(this._separator);
81 this._onControlStateChanged();
84 scroll: function(event) {
85 this._output.scroll(event);
88 separatorLastItem: function(last) {
89 log("separatorLastItem");
92 this._separator.destroy();
93 this._separator = new PopupMenu.PopupSeparatorMenuItem();
96 this.addMenuItem(this._separator, 999);
98 this.addMenuItem(this._separator, 2);
102 _streamAdded: function(control, id) {
103 if (id in this._sinks) {
107 if (id in this._outputs) {
111 let stream = control.lookup_stream_id(id);
113 if (stream["is-event-stream"]) {
115 } else if (stream instanceof Gvc.MixerSinkInput) {
116 let s = new Widget.AppOutputStreamSlider(this._control);
119 this.addMenuItem(s.item);
120 } else if (stream instanceof Gvc.MixerSink) {
121 let s = new Volume.OutputStreamSlider(this._control);
123 this._outputs[id] = s;
127 _streamRemoved: function(control, id) {
128 if (id in this._sinks) {
129 this._sinks[id].item.destroy();
130 delete this._sinks[id];
131 } else if (id in this._outputs) {
132 this._outputs[id].item.destroy();
133 delete this._outputs[id];
137 _onControlStateChanged: function() {
138 if (this._control.get_state() == Gvc.MixerControlState.READY) {
142 let streams = this._control.get_streams();
143 for (let i = 0; i < streams.length; i++) {
144 this._streamAdded(this._control, streams[i].id);
148 this.emit('icon-changed');
151 _readOutput: function() {
152 this._output.stream = this._control.get_default_sink();
155 _readInput: function() {
156 this._input.stream = this._control.get_default_source();
159 getIcon: function() {
160 return this._output.getIcon();