deep-roon-mcp 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15525,7 +15525,7 @@ var require_lib2 = __commonJS({
15525
15525
  var version2;
15526
15526
  var init_package = __esm({
15527
15527
  "package.json"() {
15528
- version2 = "0.3.0";
15528
+ version2 = "0.3.2";
15529
15529
  }
15530
15530
  });
15531
15531
 
@@ -49397,7 +49397,10 @@ async function nowPlaying() {
49397
49397
  if (r.state === "stopped") return r;
49398
49398
  const np = obj(c, field2(z2, "NowPlaying"));
49399
49399
  const tr = obj(c, field2(items(c, field2(np, "Tracks"))[0], "Track"));
49400
- if (tr && field2(tr, "Title")) {
49400
+ const lines = off?.now_playing?.three_line;
49401
+ const t = String(field2(tr, "Title") ?? "").toLowerCase(), l1 = String(lines?.line1 ?? "").toLowerCase();
49402
+ const stream = !!l1 && !!t && !l1.includes(t) && !t.includes(l1);
49403
+ if (tr && field2(tr, "Title") && !stream) {
49401
49404
  const al = obj(c, field2(tr, "Album"));
49402
49405
  r.title = field2(tr, "Title");
49403
49406
  r.artist = clean(field2(al, "PerformedBy"));
@@ -49407,7 +49410,6 @@ async function nowPlaying() {
49407
49410
  const l = field2(tr, "LengthSeconds");
49408
49411
  if (typeof l === "number") r.length = duration3(l);
49409
49412
  } else {
49410
- const lines = off?.now_playing?.three_line;
49411
49413
  if (lines?.line1) {
49412
49414
  r.title = lines.line1;
49413
49415
  if (lines.line2) r.artist = lines.line2;
@@ -49418,7 +49420,7 @@ async function nowPlaying() {
49418
49420
  const pos = field2(z2, "SeekPosition");
49419
49421
  if (typeof pos === "number") r.position = duration3(pos);
49420
49422
  const left = field2(obj(c, field2(z2, "Queue")), "TrackCountRemaining");
49421
- if (typeof left === "number") r.tracks_left_in_queue = left;
49423
+ if (typeof left === "number" && !r.source) r.tracks_left_in_queue = left;
49422
49424
  return r;
49423
49425
  });
49424
49426
  return { zones: out };
@@ -49866,6 +49868,14 @@ async function playTracks(keys, zoneName, how) {
49866
49868
  __name(playTracks, "playTracks");
49867
49869
  var BUTTONS = { pause: "Pause", play: "Play", playpause: "PlayPause", stop: "Stop", next: "Next", previous: "Previous" };
49868
49870
  async function control2(zoneName, action) {
49871
+ if (action === "release") {
49872
+ return withCore(async (c) => {
49873
+ const z2 = findZone(c, zoneName);
49874
+ c.remoting.callMethodNoReply(z2.oid, formatMethodSignature("Zone", "Suspend", []), Buffer.alloc(0));
49875
+ log(`control: Suspend on ${z2.name}`);
49876
+ return { ok: true, zone: z2.name, action };
49877
+ });
49878
+ }
49869
49879
  const m = BUTTONS[action];
49870
49880
  if (!m) throw new RoonError(`Unknown action; choose from ${Object.keys(BUTTONS).join(", ")}`, "invalid");
49871
49881
  const r = await withCore(async (c) => {
@@ -50128,10 +50138,10 @@ function registerControlTools(server, internal = true) {
50128
50138
  }, ({ keys, zone: zn, mode: m }) => run(() => playTracks(keys, zn, m ?? "now")));
50129
50139
  reg("roon_control", {
50130
50140
  title: "Transport",
50131
- description: "The buttons of a Roon zone: pause, play (resume), playpause, stop, next, previous. Only on an explicit request, never as a probe.",
50132
- inputSchema: { zone, action: external_exports.enum(["pause", "play", "playpause", "stop", "next", "previous"]) },
50141
+ description: "The buttons of a Roon zone: pause, play (resume), playpause, stop, next, previous \u2014 and release: let go of the audio device right away (what Roon does by itself a few seconds after a pause), so another source can use the speaker. Only on an explicit request, never as a probe.",
50142
+ inputSchema: { zone, action: external_exports.enum(["pause", "play", "playpause", "stop", "next", "previous", "release"]) },
50133
50143
  annotations: PLAYS
50134
- }, ({ zone: zn, action }) => run(() => internal ? control2(zn, action) : control(zn, action)));
50144
+ }, ({ zone: zn, action }) => run(() => internal ? control2(zn, action) : action === "release" ? Promise.reject(new Error("release needs Roon's internal protocol (switched off)")) : control(zn, action)));
50135
50145
  reg("roon_seek", {
50136
50146
  title: "Seek",
50137
50147
  description: "Jump to a position in the track that plays on a Roon zone, in seconds from the start. Only on an explicit request.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deep-roon-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "An MCP server for Roon that reaches the parts the official API doesn't: reviews, biographies, Qobuz's and TIDAL's shelves, TIDAL's playlists, your history, search across your library and the streaming services",
5
5
  "license": "Apache-2.0",
6
6
  "author": "René Bouwmeester <21277119+renebouwmeester@users.noreply.github.com>",