Build extensions for the GNOME desktop environment

Among many new features in GNOME 3, the most exciting one is the ability to build extensions. Here’s how it’s done...

Building LUD Volume Control Extender

Step 06

Setting up libraries

Now that we are acquainted with the basics of GNOME extensions, it’s time to build our LUD Volume Control Extender.

Let’s start with the libraries we will be using:


Clutter is a popular GNOME UI toolkit:

const Clutter =;

In the following statement we are importing GNOME Volume Control library:

const Gvc =;

Standard GNOME Widgets:

const St =;

Provide support for pop-up menus:

const PopupMenu = imports.

Steo 07

Building the UI

Instead of designing our own volume control, we will be relying on the one provided by GNOME Shell. We will be using the same icon and for the most part we will also keep all its existing functionality.


Building a pop-up menu for the Extended Volume Control:

AdvPopupSwitchMenuItem.prototype = {
   __proto__: PopupMenu.
   _init: function(text, active,
gicon, params) {
   “ “ + text + “  “,
   this._icon = new St.Icon({
   gicon:        gicon,
   style_class: “adv-volume-icon”

Here we are rebuilding the switch:


The following container contains the various UI elements for the new volume control:

   let labelBox = new
St.BoxLayout({vertical: false});
{expand: false, x_fill: false, x_
align: St.Align.START});
{expand: false, x_fill: false, x_
align: St.Align.START});
{expand: true, x_fill: true, x_
align: St.Align.END});
   this.addActor(labelBox, {span:
-1, expand: true });

Step 08

Setting up the Volume Control Mixer and Sound Streams

In this step we will setting up the new Volume Control Mixer and Sound Streams.


Set up the mixer and audio output controls:

 AdvMixer.prototype = {
    _init: function(mixer) {
    this._mixer = mixer;
    this._control = mixer._control;
    this._separator = new PopupMenu.
    this._items = {};
    this._outputs = {};
    this._outputMenu = new PopupMenu.
 addMenuItem(this._separator, 1);
    this._streamAddedId = this._
 Lang.bind(this, this._streamAdded)
    this._streamRemovedId = this._
 Lang.bind(this, this._streamRemoved)
    this._defaultSinkChangedId =
 Lang.bind(this, this._

Step 09

Enable and disable extension methods

In the ‘enable’ function we are creating a new instance of AdvMixer, putting it in the panel where the volume control is present.

 function enable() {
 if (Main.panel.statusArea[‘volume’]
 && !advMixer) {
 advMixer = new AdvMixer(Main.panel.
 function disable() {
 if (advMixer) {
 advMixer = null;

Step 10

LUD Volume Control Extender in action

After making the changes, press Alt+F2, then type ‘r’ in the console and hit Enter to restart GNOME Shell. This will reload the extension with the latest changes.

You will notice that there are no new icons this time. Click on the Volume icon and you will notice some subtle differences.

You will notice that there is now a small arrow after Volume which, when clicked, allows you to switch to various audio output devices (if available).

You now have the ability to see which applications are using the sound output, and you get the volume controls for each of them. You can also mute individual applications using the ON/OFF toggle.

Changing GNOME

As you can see, with the LUD Volume Control Extender we have made a significant change in the existing GNOME Shell volume control. It almost feels like it is not an extension, but something which is actually built into the GNOME system. That is the beauty of GNOME Shell extensions, and they exist for a very good reason. When GNOME 3 was released, a lot of people hated the way it worked but still liked the elegance and simplicity that it offered. So they wanted a way to make changes to the GNOME Shell while keeping the overall experience intact. GNOME Shell extensions provided that way.

Credit where credit’s due

The LUD Volume Controller Extender uses the code from Harry Karvonen’s AdvancedVolumeMixer project