228 lines
6.1 KiB
QML
Executable File
228 lines
6.1 KiB
QML
Executable File
// Reworked the PlayerController a bit
|
|
|
|
|
|
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import QtQml.Models
|
|
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import Quickshell.Services.Mpris
|
|
// import qs
|
|
|
|
Singleton {
|
|
id: root;
|
|
property Mpris mpris: Mpris;
|
|
property MprisPlayer activePlayer: findSpotify();
|
|
|
|
signal trackChanged(reverse: bool);
|
|
|
|
property bool __reverse: false;
|
|
|
|
property var activeTrack;
|
|
|
|
property string activeTrackPositionFormated: "0:00";
|
|
property string activeTrackLengthFormated: "0:00";
|
|
|
|
PersistentProperties {
|
|
id: persist
|
|
reloadableId: "MusicWidget";
|
|
property string lastActivePlayerIdentify: "";
|
|
|
|
onReloaded: {
|
|
root.setActivePlayerFromIdentity(lastActivePlayerIdentify)
|
|
root.updateActiveTrackPosition()
|
|
}
|
|
onLoaded: {
|
|
root.setActivePlayerFromIdentity(lastActivePlayerIdentify)
|
|
root.updateActiveTrackPosition()
|
|
}
|
|
}
|
|
|
|
Instantiator {
|
|
model: Mpris.players;
|
|
|
|
Connections {
|
|
required property MprisPlayer modelData;
|
|
target: modelData;
|
|
|
|
Component.onCompleted: {
|
|
if (root.trackedPlayer == null || modelData.isPlaying) {
|
|
root.trackedPlayer = modelData;
|
|
}
|
|
}
|
|
|
|
Component.onDestruction: {
|
|
if (root.trackedPlayer == null || !root.trackedPlayer.isPlaying) {
|
|
for (const player of Mpris.players.values) {
|
|
if (player.playbackState.isPlaying) {
|
|
root.trackedPlayer = player;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (trackedPlayer == null && Mpris.players.values.length != 0) {
|
|
trackedPlayer = Mpris.players.values[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
function onPlaybackStateChanged() {
|
|
console.log("Playback state has been changed")
|
|
// if (root.trackedPlayer !== modelData) root.trackedPlayer = modelData;
|
|
}
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: activePlayer
|
|
|
|
function onPostTrackChanged() {
|
|
root.updateTrack();
|
|
}
|
|
|
|
function onTrackArtUrlChanged() {
|
|
console.log("arturl:", activePlayer.trackArtUrl)
|
|
//root.updateTrack();
|
|
if (root.activePlayer.uniqueId == root.activeTrack.uniqueId && root.activePlayer.trackArtUrl != root.activeTrack.artUrl) {
|
|
// cantata likes to send cover updates *BEFORE* updating the track info.
|
|
// as such, art url changes shouldn't be able to break the reverse animation
|
|
const r = root.__reverse;
|
|
root.updateTrack();
|
|
root.__reverse = r;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
onActivePlayerChanged: this.updateTrack();
|
|
|
|
function setPlayerByIdentity(id: string) {
|
|
for (var i = 0; i < 9; i++) {
|
|
console.log(i)
|
|
}
|
|
mpris.players
|
|
}
|
|
|
|
function updateTrack() {
|
|
this.activeTrack = {
|
|
uniqueId: this.activePlayer?.uniqueId ?? 0,
|
|
artUrl: this.activePlayer?.trackArtUrl ?? "",
|
|
title: this.activePlayer?.trackTitle || "Unknown Title",
|
|
artist: this.activePlayer?.trackArtist || "Unknown Artist",
|
|
album: this.activePlayer?.trackAlbum || "Unknown Album",
|
|
};
|
|
|
|
this.trackChanged(__reverse);
|
|
this.__reverse = false;
|
|
}
|
|
|
|
|
|
|
|
property bool isPlaying: this.activePlayer && this.activePlayer.isPlaying;
|
|
property bool canTogglePlaying: this.activePlayer?.canTogglePlaying ?? false;
|
|
function togglePlaying() {
|
|
if (this.canTogglePlaying) this.activePlayer.togglePlaying();
|
|
}
|
|
|
|
property bool canGoPrevious: this.activePlayer?.canGoPrevious ?? false;
|
|
function previous() {
|
|
if (this.canGoPrevious) {
|
|
this.__reverse = true;
|
|
this.activePlayer.previous();
|
|
}
|
|
}
|
|
|
|
property bool canGoNext: this.activePlayer?.canGoNext ?? false;
|
|
function next() {
|
|
if (this.canGoNext) {
|
|
this.__reverse = false;
|
|
this.activePlayer.next();
|
|
}
|
|
}
|
|
|
|
property bool canChangeVolume: this.activePlayer && this.activePlayer.volumeSupported && this.activePlayer.canControl;
|
|
|
|
property bool loopSupported: this.activePlayer && this.activePlayer.loopSupported && this.activePlayer.canControl;
|
|
property var loopState: this.activePlayer?.loopState ?? MprisLoopState.None;
|
|
function setLoopState(loopState: var) {
|
|
if (this.loopSupported) {
|
|
this.activePlayer.loopState = loopState;
|
|
}
|
|
}
|
|
|
|
property bool shuffleSupported: this.activePlayer && this.activePlayer.shuffleSupported && this.activePlayer.canControl;
|
|
property bool hasShuffle: this.activePlayer?.shuffle ?? false;
|
|
function setShuffle(shuffle: bool) {
|
|
if (this.shuffleSupported) {
|
|
this.activePlayer.shuffle = shuffle;
|
|
}
|
|
}
|
|
|
|
function setActivePlayer(player: MprisPlayer) {
|
|
const targetPlayer = player;
|
|
console.log(`setactive: ${targetPlayer} from ${activePlayer}`)
|
|
|
|
persist.lastActivePlayerIdentify = targetPlayer.identity
|
|
this.activePlayer = player;
|
|
}
|
|
|
|
function setActivePlayerFromIdentity(identify: string) {
|
|
for (x in root.mpris.players) {
|
|
if (x.identify == identify) {
|
|
this.activePlayer = x
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
// only emit the signal when the position is actually changing.
|
|
running: root.activePlayer.playbackState == MprisPlaybackState.Playing
|
|
// Make sure the position updates at least once per second.
|
|
interval: 1000
|
|
repeat: true
|
|
// emit the positionChanged signal every second.
|
|
onTriggered: root.updateActiveTrackPosition()
|
|
}
|
|
|
|
function updateActiveTrackPosition() {
|
|
activeTrackPositionFormated = Math.floor(root.activePlayer.position / 60) + ":" + ("0" + Math.floor(root.activePlayer.position % 60)).slice(-2)
|
|
activeTrackLengthFormated = Math.floor(root.activePlayer.length / 60) + ":" + ("0" + Math.floor(root.activePlayer.length % 60)).slice(-2)
|
|
}
|
|
|
|
function update() {
|
|
updateActiveTrackPosition()
|
|
}
|
|
|
|
function trackPositionFormatter(position: double): string {
|
|
return Math.floor(position / 60) + ":" + ("0" + Math.floor(position % 60)).slice(-2)
|
|
}
|
|
|
|
function findSpotify(): MprisPlayer {
|
|
const players = Mpris.players
|
|
for (const player of players.values) {
|
|
if (player.identity == "Spotify") {
|
|
return player
|
|
}
|
|
}
|
|
return undefined
|
|
console.log("");
|
|
}
|
|
|
|
IpcHandler {
|
|
target: "mpris"
|
|
|
|
function pauseAll(): void {
|
|
for (const player of Mpris.players.values) {
|
|
if (player.canPause) player.pause();
|
|
}
|
|
}
|
|
|
|
function playPause(): void { root.togglePlaying(); }
|
|
function previous(): void { root.previous(); }
|
|
function next(): void { root.next(); }
|
|
}
|
|
}
|