Skip to content

Instantly share code, notes, and snippets.

@marco79cgn
Last active January 6, 2024 07:46
Show Gist options
  • Save marco79cgn/98616fcbb2dfdbd752b33a452208bcc8 to your computer and use it in GitHub Desktop.
Save marco79cgn/98616fcbb2dfdbd752b33a452208bcc8 to your computer and use it in GitHub Desktop.
A scriptable widget that shows what's playing on SONOS
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: cyan; icon-glyph: magic;
// the node sonos http api base url (running on your Pi for example)
let sonosBaseUrl = "http://192.168.178.10:5005"
// optional for cover art: the ip address of one of your Sonos speakers
let sonosPlayerUrl = "http://192.168.178.38:1400"
let param = args.widgetParameter
let nowPlaying = await loadNowPlaying()
let widget = await createWidget(nowPlaying)
Script.setWidget(widget)
Script.complete()
//widget.presentSmall()
async function createWidget(nowPlaying) {
let widget = new ListWidget()
widget.setPadding(5, 6, 0, 5)
// show album art if configured and available
let albumArtUrl = nowPlaying.currentTrack.albumArtUri
if(param === "cover" && albumArtUrl != null && albumArtUrl.length > 1) {
if(albumArtUrl.indexOf("http") > -1) {
let albumArt = await loadImage(albumArtUrl)
widget.backgroundImage = albumArt
} else {
let albumArt = await loadImage(sonosPlayerUrl + nowPlaying.currentTrack.albumArtUri)
widget.backgroundImage = albumArt
}
}
// set gradient background
let startColor = new Color("#da2f68e6")
let endColor = new Color("#c30645b3")
let gradient = new LinearGradient()
gradient.colors = [startColor, endColor]
gradient.locations = [0, 1]
widget.backgroundColor = new Color("#b00a0f")
widget.backgroundGradient = gradient
let sonosLogo = await loadImage("https://pisces.bbystatic.com/image2/BestBuy_US/Gallery/sonos_logo_white_2.png")
let image = widget.addImage(sonosLogo)
image.imageSize = new Size(35,15)
image.centerAlignImage()
widget.addSpacer(5)
let nowText = widget.addText("NOW PLAYING:")
nowText.font = Font.boldSystemFont(12)
nowText.textColor = Color.white()
nowText.centerAlignText()
nowText.textOpacity = 0.8
// add title and artist
let shortTitle = ""
if (nowPlaying.currentTrack.type === "radio" && albumArtUrl != null && albumArtUrl.indexOf("radioparadise") === -1) {
widget.addSpacer(15)
if(nowPlaying.currentTrack.title.indexOf("x-sonosapi") === -1) {
shortTitle = demasterRadio(nowPlaying.currentTrack.title)
}
} else {
shortTitle = demaster(nowPlaying.currentTrack.title)
}
let titleTxt = widget.addText(shortTitle)
titleTxt.font = Font.semiboldSystemFont(12)
titleTxt.textColor = Color.white()
titleTxt.centerAlignText()
let artistTxt = widget.addText(nowPlaying.currentTrack.artist)
artistTxt.font = Font.semiboldSystemFont(12)
artistTxt.textColor = Color.cyan()
artistTxt.centerAlignText()
if (nowPlaying.currentTrack.type !== "radio" || (albumArtUrl != null && albumArtUrl.indexOf("radioparadise") !== -1)) {
let separatorText = widget.addText("—")
separatorText.textColor = Color.white()
separatorText.centerAlignText()
separatorText.textOpacity = 0.7
let nextText = widget.addText("NEXT UP:")
nextText.font = Font.boldSystemFont(12)
nextText.textColor = Color.white()
nextText.centerAlignText()
nextText.textOpacity = 0.8
// add next title and artist
let shortNextTitle = demaster(nowPlaying.nextTrack.title)
let nextTitleTxt = widget.addText(shortNextTitle)
nextTitleTxt.textColor = Color.white()
nextTitleTxt.font = Font.semiboldSystemFont(12)
nextTitleTxt.centerAlignText()
let nextArtistTxt = widget.addText(nowPlaying.nextTrack.artist)
nextArtistTxt.textColor = Color.cyan()
nextArtistTxt.font = Font.semiboldSystemFont(12)
nextArtistTxt.centerAlignText()
}
if(config.runsInApp) {
let request = new Request(sonosBaseUrl + "/playpause")
request.allowInsecureRequest = true
let json = await request.loadJSON()
Safari.open("shortcuts://run-shortcut?name=SpringBoard")
}
widget.addSpacer()
return widget
}
// load and parse a restful json api
async function loadNowPlaying() {
let url = sonosBaseUrl + "/state"
let req = new Request(url)
req.allowInsecureRequest = true
let json = await req.loadJSON()
console.log(json)
return json
}
// download an image from a given url
async function loadImage(imgUrl) {
console.log(imgUrl)
let req = new Request(imgUrl)
req.allowInsecureRequest = true
let image = await req.loadImage()
return image
}
function demaster(trackName) {
let shortenedTrackName = trackName.split(" - ")
shortenedTrackName = shortenedTrackName[0].split(" (Live")
shortenedTrackName = shortenedTrackName[0].split(" (feat")
console.log("short name: " + shortenedTrackName[0])
return shortenedTrackName[0]
}
function demasterRadio(trackName) {
let shortenedTrackName = trackName.split(" |")
shortenedTrackName = shortenedTrackName[0].split(" --")
console.log("short name: " + shortenedTrackName[0])
return shortenedTrackName[0]
}
@Token2K
Copy link

Token2K commented Jun 8, 2021

Hi Marco,

... vielleicht kannst du mit der Fehlermeldung mehr anfangen, und evtl. mir weiterhelfen?

2021-06-09 00:51:45: {"volume":13,"mute":false,"elapsedTimeFormatted":"00:00:00","currentTrack":{"artist":"Radio Brocken","trackUri":"x-sonosapi-stream:rpde_svc_74?sid=232&flags=32&sn=2","albumArtUri":"/getaa?s=1&u=x-sonosapi-stream%3arpde_svc_74%3fsid%3d232%26flags%3d32%26sn%3d2","absoluteAlbumArtUri":"http://192.168.2.115:1400/getaa?s=1&u=x-sonosapi-stream%3arpde_svc_74%3fsid%3d232%26flags%3d32%26sn%3d2","duration":0,"stationName":"Radio Brocken","type":"radio","uri":"x-sonosapi-stream:rpde_svc_74?sid=232&flags=32&sn=2"},"trackNo":1,"elapsedTime":0,"equalizer":{"nightMode":false,"treble":-1,"bass":2,"loudness":true,"speechEnhancement":false},"playbackState":"STOPPED","playMode":{"shuffle":false,"crossfade":false,"repeat":"none"},"nextTrack":{"duration":0,"uri":"","title":"","album":"","albumArtUri":"","artist":""}}
2021-06-09 00:51:45: https://pisces.bbystatic.com/image2/BestBuy_US/Gallery/sonos_logo_white_2.png
2021-06-09 00:51:45: Error on line 60:37: TypeError: undefined is not an object (evaluating 'nowPlaying.currentTrack.title.indexOf')

Danke

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment