koolskateguy89 / gnome-shell-extension-spotify-controller

A GNOME Shell extension to control Spotify in the top bar
https://extensions.gnome.org/extension/4013/spotify-controller/
GNU General Public License v3.0
45 stars 4 forks source link

V14 Error Bug #19

Open rogerioo opened 2 years ago

rogerioo commented 2 years ago

I've recently updated to V14, but something went wrong an I cannot use the extension anymore. As how I click on the settings button shows nothing, I've no logs to share here.

I'm on Ubuntu 20.04 and Gnome 3.36.8

koolskateguy89 commented 2 years ago

Can you try deleting these lines and let me know if it works

rogerioo commented 2 years ago

@koolskateguy89 I don't really know how to do this.. I've just installed your extension though Gnome Extensions page. Can you walk me though the steps?

koolskateguy89 commented 2 years ago

@rogerioo

  1. Open ~/.local/share/gnome-shell/extensions/spotify-controller@koolskateguy89/mediaPlayer.js in a text editor
  2. Delete lines 37-41
  3. Logout then log back in
  4. Try to enable the extension
rogerioo commented 2 years ago

@koolskateguy89 It didn't worked, and I haven't still any logs to show. It keeps showing this error on the extension. image

koolskateguy89 commented 2 years ago

@rogerioo Can you replace the contents of ~/.local/share/gnome-shell/extensions/spotify-controller@koolskateguy89/extension.js with:

// GNOME APIs are under the `gi` namespace (except Cairo)
// See: https://gjs-docs.gnome.org/
const { Gio, GObject, St } = imports.gi;

// GNOME Shell imports
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();

// helper variables
let lastExtensionPlace, lastExtensionIndex;
let showInactive;
let hide = true;

// signals
let settingsSignals;

const backward  = 'media-skip-backward-symbolic';
const forward   = 'media-skip-forward-symbolic';
const play      = 'media-playback-start-symbolic';
const pause     = 'media-playback-pause-symbolic';

let settings;

/**
 * A Gio.DBuxProxy of the `org.mpris.MediaPlayer2.Player` interface.
 * @typedef {Object} MediaPlayerProxy
 * @property {string} PlaybackStatus
 */

/**
 * @callback playerConsumer
 * @param {MediaPlayer} player
 */

/**
 * A non-player specific wrapper of a proxy for a media player.
 * @todo Write the documentation.
 */
class MediaPlayer {
    // thanks esenliyim - https://github.com/esenliyim/sp-tray/blob/master/dbus.js
    // https://wiki.gnome.org/Gjs/Examples/DBusClient
    // https://www.andyholmes.ca/articles/dbus-in-gjs.html#high-level-proxies
    static path = '/org/mpris/MediaPlayer2';
    static playerInterface = `
    <node>
    <interface name="org.mpris.MediaPlayer2.Player">
        <property name="PlaybackStatus" type="s" access="read" />
        <method name="Next" />
        <method name="Previous" />
        <method name="PlayPause" />
    </interface>
    </node>
    `;

    // Declare the proxy class based on the interface
    static PlayerProxy = Gio.DBusProxy.makeProxyWrapper(MediaPlayer.playerInterface);

    onAppeared;
    onVanished;
    onPropertiesChanged;
    proxy;
    proxySignals;

    /**
     * @param {playerConsumer=} onAppeared
     * @param {playerConsumer=} onVanished
     * @param {playerConsumer=} onPropertiesChanged
     */
    constructor(onAppeared, onVanished, onPropertiesChanged) {
        this.onAppeared = onAppeared;
        this.onVanished = onVanished;
        this.onPropertiesChanged = onPropertiesChanged;

        this.proxy = null;
        this.proxySignals = [];
    }

    /**
     * @param {string} dest - The well-known name
     */
    setupProxy(dest = 'org.mpris.MediaPlayer2.spotify') {
        if (this.proxy)
            return;

        try {
            // Get the MediaPlayer instance from the bus
            this.proxy = new MediaPlayer.PlayerProxy(Gio.DBus.session, dest, MediaPlayer.path);
        } catch (e) {
            logError(e);
            return;
        }

        this.proxySignals.push(this.proxy.connect(
            "g-properties-changed",
            (proxy, changed, invalidated) => {
                this.onPropertiesChanged?.(this);
            }
        ));

        // https://www.andyholmes.ca/articles/dbus-in-gjs.html#low-level-proxies
        this.proxySignals.push(this.proxy.connect(
            "notify::g-name-owner",
            (proxy, pspec) => {
                if (proxy.g_name_owner === null) {
                    log(`${proxy.g_name} has vanished`);
                    this.onVanished?.(this);
                } else {
                    log(`${proxy.g_name} has appeared`);
                    this.onAppeared?.(this);
                }
            }
        ));
    }

    destroy() {
        this.proxySignals.forEach(signal => this.proxy.disconnect(signal));
    }

    get isActive() {
        return this.proxy.g_name_owner !== null;
    }

    get isPlaying() {
        return this.isActive && this.proxy.PlaybackStatus === 'Playing';
    }

    next() {
        this.proxy.NextSync();
    }

    previous() {
        this.proxy.PreviousSync();
    }

    playPause() {
        this.proxy.PlayPauseSync();
    }
}

function styleStr(direction, iconType) {
    let style;
    if (iconType) {
        style = `padding-${direction}: ${settings.get_int(`${direction}-padding`)}px;`
    } else {
        // called by toggle
        style = '';
        iconType = direction;
    }

    const useSameColors = settings.get_boolean('same-color-buttons');
    iconType = useSameColors ? 'prev' : iconType;
    style += `color: ${settings.get_string(`${iconType}-icon-color`)};`

    return style;
}

const Previous = GObject.registerClass(
class Previous extends St.Icon {
    _init(spotify, controlBar) {
        super._init({
            track_hover: true,
            can_focus: true,
            reactive: true,
            icon_name: backward,
            style_class: 'system-status-icon',
            style: styleStr('left', 'prev'),
        });

        // Listen for update of left padding in settings
        settingsSignals.push(settings.connect(
            'changed::left-padding',
            this._styleChanged.bind(this)
        ));

        settingsSignals.push(settings.connect(
            'changed::prev-icon-color',
            controlBar._sameColorButtonsChanged.bind(controlBar)
        ));

        this.connect('button-press-event', () => {
            if (!hide) {
                spotify.previous();
            }
        });
    }

    _styleChanged() {
        this.set_style(styleStr('left', 'prev'));
    }
});

const Next = GObject.registerClass(
class Next extends St.Icon {
    _init(spotify) {
        super._init({
            track_hover: true,
            can_focus: true,
            reactive: true,
            icon_name: forward,
            style_class: 'system-status-icon',
            style: styleStr('right', 'next'),
        });

        // Listen for update of right padding in settings
        settingsSignals.push(settings.connect(
            'changed::right-padding',
            this._styleChanged.bind(this)
        ));

        settingsSignals.push(settings.connect(
            'changed::next-icon-color',
            this._styleChanged.bind(this)
        ));

        this.connect('button-press-event', () => {
            if (!hide) {
                spotify.next();
            }
        });
    }

    _styleChanged() {

        this.set_style(styleStr('right', 'next'));
    }
});

const Toggle = GObject.registerClass(
class Toggle extends St.Icon {
    _init(spotify) {
        super._init({
            track_hover: true,
            can_focus: true,
            reactive: true,
            icon_name: play,
            style_class: 'system-status-icon',
            style: styleStr('play'),
        });

        settingsSignals.push(settings.connect(
            'changed::pause-icon-color',
            this._styleChanged.bind(this)
        ));

        settingsSignals.push(settings.connect(
            'changed::play-icon-color',
            this._styleChanged.bind(this)
        ));

        this.connect('button-press-event', () => {
            if (!hide) {
                spotify.playPause();
            }
        });
    }

    _styleChanged() {
        const current = this.icon_name === play ? 'play' : 'pause';
        this.set_style(styleStr(current));
    }

    _pauseIcon() {
        this.icon_name = pause;
        this._styleChanged();
    }

    _playIcon() {
        this.icon_name = play;
        this._styleChanged();
    }
});

const ControlBar = GObject.registerClass(
class ControlBar extends PanelMenu.Button {
    _init(spotify) {
        super._init();

        this.previous = new Previous(spotify, this);

        this.next = new Next(spotify);

        this.toggle = new Toggle(spotify);

        this.buttons = [
            this.previous,
            this.toggle,
            this.next,
        ];

        settingsSignals.push(settings.connect(
            'changed::same-color-buttons',
            this._sameColorButtonsChanged.bind(this)
        ));

        this.bar = new St.BoxLayout();

        this.buttons.forEach(btn => this.bar.add_child(btn));

        if ((typeof this.add_child) === 'function')
            this.add_child(this.bar);
        else
            this.actor.add_actor(this.bar);
    }

    _sameColorButtonsChanged() {
        this.buttons.forEach(btn => btn._styleChanged());
    }

    _insertAt(box, index) {
        box.insert_child_at_index(this.container, index);
    }

    _removeFrom(box) {
        box.remove_actor(this.container);
    }

    destroy() {
        this.previous.destroy();
        this.next.destroy();
        this.toggle.destroy();

        this.bar.destroy();
        super.destroy();
    }
});

class Extension {
    spotify;
    controlBar;

    constructor() {
    }

    enable() {
        this._initSettings();

        const refresh = this._refresh.bind(this);
        this.spotify = new MediaPlayer(refresh, refresh, refresh);
        this.spotify.setupProxy();

        this.controlBar = new ControlBar(this.spotify);

        this._refresh();
    }

    _initSettings() {
        settings = ExtensionUtils.getSettings();
        settingsSignals = [];

        lastExtensionPlace = settings.get_string('extension-place');
        lastExtensionIndex = settings.get_int('extension-index');

        settingsSignals.push(settings.connect(
            'changed::extension-place',
            this.onExtensionLocationChanged.bind(this)
        ));

        settingsSignals.push(settings.connect(
            'changed::extension-index',
            this.onExtensionLocationChanged.bind(this)
        ));

        settingsSignals.push(settings.connect(
            'changed::show-inactive',
            this._refresh.bind(this)
        ));
    }

    disable() {
        settingsSignals.forEach((signal) => settings.disconnect(signal));
        settingsSignals = null;

        settings = null;

        this.spotify.destroy();

        this.controlBar.destroy();
        hide = true;
    }

    _refresh() {
        if (this.spotify.isActive) {
            if (hide) {
                // first time extension shows
                log(`Showing spotify-controller: Spotify owner vanished`);
                hide = false;
                this.onExtensionLocationChanged(settings);
            }

            this.controlBar.toggle[this.spotify.isPlaying ? '_pauseIcon' : '_playIcon']();
        } else {
            log(`Hiding spotify-controller: Spotify owner disappeared`);
            hide = true;

            this.controlBar.toggle._playIcon();

            const newShowInactive = settings.get_boolean('show-inactive');

            if (newShowInactive !== showInactive) {
                showInactive = newShowInactive;
                if (showInactive) {
                    this.onExtensionLocationChanged(settings);
                }
            }

            if (!showInactive) {
                let removePanel = getPanel(lastExtensionPlace);
                this.controlBar._removeFrom(removePanel);
            }
        }
    }

    // Remove from old box & move to new box
    // USE THIS FOR ADDING TO TOP BAR
    onExtensionLocationChanged(settings, settingsKey) {
        const newExtensionPlace = settings.get_string('extension-place');
        const newExtensionIndex = settings.get_int('extension-index');

        let removeBox = getPanel(lastExtensionPlace);
        let insertBox = getPanel(newExtensionPlace);

        this.controlBar._removeFrom(removeBox);
        if (!hide || showInactive)
            this.controlBar._insertAt(insertBox, newExtensionIndex);

        lastExtensionPlace = newExtensionPlace;
        lastExtensionIndex = newExtensionIndex;
    }
}

function getPanel(place) {
    switch (place) {
        case 'left':
            return Main.panel._leftBox;
        case 'center':
            return Main.panel._centerBox;
        default:
            return Main.panel._rightBox;
    }
}

function debug(text) {
    log(`\n\n\n${text}\n\n\n`);
}

function init() {
    return new Extension();
}
rogerioo commented 2 years ago

I've missed this e-mail.. I'll try tomorrow. Ok?

koolskateguy89 commented 2 years ago

@rogerioo any update?

rogerioo commented 2 years ago

@koolskateguy89 It changed nothing.. still with error.

parapara29 commented 2 years ago

@koolskateguy89 im suffering from the same issue as well, the extension manager shows me the following error: SyntaxError: fields are not currently supported. Im on ubuntu 20.04, gnome version 3.36.8

koolskateguy89 commented 2 years ago

@koolskateguy89 im suffering from the same issue as well, the extension manager shows me the following error: SyntaxError: fields are not currently supported. Im on ubuntu 20.04, gnome version 3.36.8

Ok I think I know what the problem is now, I should be able to fix it tonight when I get home

rogerioo commented 2 years ago

@koolskateguy89 Still not working here!

parapara29 commented 2 years ago

@koolskateguy89 same issue here, this is the error showing on extension manager: SyntaxError: expected expression, got '.'