mpris: Split widgets from data objects

Separate widgets from data objects so that in a future commit the
widgets can be moved to messageList.js

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3429>
This commit is contained in:
Julian Sparber 2024-05-09 17:14:45 +02:00
parent 45d7b9673a
commit c102d8c5ba

View File

@ -1,7 +1,6 @@
import Gio from 'gi://Gio'; import Gio from 'gi://Gio';
import GObject from 'gi://GObject'; import GObject from 'gi://GObject';
import Shell from 'gi://Shell'; import Shell from 'gi://Shell';
import * as Signals from '../misc/signals.js';
import * as Main from './main.js'; import * as Main from './main.js';
import * as MessageList from './messageList.js'; import * as MessageList from './messageList.js';
@ -19,7 +18,7 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.'; const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
export const MediaMessage = GObject.registerClass( const MediaMessage = GObject.registerClass(
class MediaMessage extends MessageList.Message { class MediaMessage extends MessageList.Message {
constructor(player) { constructor(player) {
super(player.source); super(player.source);
@ -42,9 +41,7 @@ class MediaMessage extends MessageList.Message {
this._player.next(); this._player.next();
}); });
this._player.connectObject( this._player.connectObject('changed', this._update.bind(this), this);
'changed', this._update.bind(this),
'closed', this.close.bind(this), this);
this._update(); this._update();
} }
@ -83,7 +80,18 @@ class MediaMessage extends MessageList.Message {
} }
}); });
export class MprisPlayer extends Signals.EventEmitter {
export const MprisPlayer = GObject.registerClass({
Properties: {
'can-play': GObject.ParamSpec.boolean(
'can-play', null, null,
GObject.ParamFlags.READABLE,
false),
},
Signals: {
'changed': {},
},
}, class MprisPlayer extends GObject.Object {
constructor(busName) { constructor(busName) {
super(); super();
@ -94,7 +102,7 @@ export class MprisPlayer extends Signals.EventEmitter {
'/org/mpris/MediaPlayer2', '/org/mpris/MediaPlayer2',
this._onPlayerProxyReady.bind(this)); this._onPlayerProxyReady.bind(this));
this._visible = false; this._canPlay = false;
this._trackArtists = []; this._trackArtists = [];
this._trackTitle = ''; this._trackTitle = '';
this._trackCoverUrl = ''; this._trackCoverUrl = '';
@ -102,6 +110,10 @@ export class MprisPlayer extends Signals.EventEmitter {
this.source = new MessageList.Source(); this.source = new MessageList.Source();
} }
get canPlay() {
return this._canPlay;
}
get status() { get status() {
return this._playerProxy.PlaybackStatus; return this._playerProxy.PlaybackStatus;
} }
@ -157,8 +169,6 @@ export class MprisPlayer extends Signals.EventEmitter {
this._playerProxy.disconnectObject(this); this._playerProxy.disconnectObject(this);
this._playerProxy = null; this._playerProxy = null;
this.emit('closed');
} }
_onMprisProxyReady() { _onMprisProxyReady() {
@ -176,7 +186,7 @@ export class MprisPlayer extends Signals.EventEmitter {
_onPlayerProxyReady() { _onPlayerProxyReady() {
this._playerProxy.connectObject( this._playerProxy.connectObject(
'g-properties-changed', () => this._updateState(), this); 'g-properties-changed', this._updateState.bind(this), this);
this._updateState(); this._updateState();
} }
@ -230,22 +240,22 @@ export class MprisPlayer extends Signals.EventEmitter {
icon: this._app?.get_icon() ?? null, icon: this._app?.get_icon() ?? null,
}); });
this.emit('changed'); const canPlay = !!this._playerProxy.CanPlay;
let visible = this._playerProxy.CanPlay; if (this.canPlay !== canPlay) {
this._canPlay = canPlay;
if (this._visible !== visible) { this.notify('can-play');
this._visible = visible;
if (visible)
this.emit('show');
else
this.emit('hide');
} }
this.emit('changed');
} }
} });
export const MediaSection = GObject.registerClass( export const MprisSource = GObject.registerClass({
class MediaSection extends MessageList.MessageListSection { Signals: {
'player-added': {param_types: [MprisPlayer]},
'player-removed': {param_types: [MprisPlayer]},
},
}, class MprisSource extends GObject.Object {
_init() { _init() {
super._init(); super._init();
@ -257,30 +267,24 @@ class MediaSection extends MessageList.MessageListSection {
this._onProxyReady.bind(this)); this._onProxyReady.bind(this));
} }
get allowed() { get players() {
return !Main.sessionMode.isGreeter; return [...this._players.values()];
} }
_addPlayer(busName) { _addPlayer(busName) {
if (this._players.get(busName)) if (this._players.has(busName))
return; return;
let player = new MprisPlayer(busName); const player = new MprisPlayer(busName);
let message = null;
player.connect('closed',
() => {
this._players.delete(busName);
});
player.connect('show', () => {
message = new MediaMessage(player);
this.addMessage(message, true);
});
player.connect('hide', () => {
this.removeMessage(message, true);
message = null;
});
this._players.set(busName, player); this._players.set(busName, player);
player.connectObject('notify::can-play',
() => {
if (player.canPlay)
this.emit('player-added', player);
else
this.emit('player-removed', player);
}, this);
} }
async _onProxyReady() { async _onProxyReady() {
@ -299,7 +303,56 @@ class MediaSection extends MessageList.MessageListSection {
if (!name.startsWith(MPRIS_PLAYER_PREFIX)) if (!name.startsWith(MPRIS_PLAYER_PREFIX))
return; return;
if (newOwner && !oldOwner) if (oldOwner) {
const player = this._players.get(name);
if (player) {
this._players.delete(name);
player.disconnectObject(this);
this.emit('player-removed', player);
}
}
if (newOwner)
this._addPlayer(name); this._addPlayer(name);
} }
}); });
export const MediaSection = GObject.registerClass(
class MediaSection extends MessageList.MessageListSection {
constructor() {
super();
this._players = new Map();
this._mediaSource = new MprisSource();
this._mediaSource.connectObject(
'player-added', (_, player) => this._addPlayer(player),
'player-removed', (_, player) => this._removePlayer(player),
this);
this._mediaSource.players.forEach(player => {
this._addPlayer(player);
});
}
_addPlayer(player) {
if (this._players.has(player))
throw new Error('Player was already added previously');
const message = new MediaMessage(player);
this._players.set(player, message);
this.addMessage(message, true);
}
_removePlayer(player) {
const message = this._players.get(player);
if (message)
this.removeMessage(message, true);
this._players.delete(player);
}
get allowed() {
return !Main.sessionMode.isGreeter;
}
});