// Copyright 2014-2025 Jesper Larsson
//
// This file is part of Klipspringer, <https://klipspringer.avadeaux.net/>
//
// Klipspringer is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Klipspringer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Klipspringer. If
// not, see <https://www.gnu.org/licenses/>.
package net.avadeaux.klipspringer;
import java.io.IOException;
import java.util.concurrent.Executor;
import net.avadeaux.klipspringer.codec.*;
public class TrackCommandInterface extends CommandInterface {
private final TrackFeeder feeder;
private final Track.List tracks;
private final PlayState state;
private final Device.Player.Factory serverOutFact;
public TrackCommandInterface(TrackFeeder feeder,
Track.List tracks,
PlayState state,
Device.Player.Factory serverOutFact,
Executor streamKeepAliveExecutor,
long streamKeepAliveTimeoutMillis)
{
super(streamKeepAliveExecutor, streamKeepAliveTimeoutMillis);
this.feeder = feeder;
this.tracks = tracks;
this.state = state;
this.serverOutFact = serverOutFact;
cmds.put("get_status", (q, w) -> {
w.append("{");
state.serverStatus(q.longValue("seen", -1), q.longValue("timeout", 0), w);
w.append("}");
});
cmds.put("set_played_get_status", (q, w) -> {
AudioStream stream = streamHandles.get(q.value("player_id", NO_PLAYER_ID));
if (stream == null) {
w.append("{\"err\":\"unknown stream\"}");
return;
}
double time = q.doubleValue("time", 0);
stream.playedMillis((long) (time*1000.0 + 0.5));
w.append("{");
state.streamStatus(time, w);
String bitrate = stream.quality();
if (bitrate != null) { w.append(",\"bitrate\":\""+bitrate+"\""); }
w.append("}");
});
cmds.put("quit", (q, w) -> {
w.append("{");
state.serverStatus(-1, 0, w);
w.append(",\"restart\": true }");
w.flush();
System.exit(130); // terminated by user
});
cmds.put("pause", (q, w) -> {
if (q.booleanValue("state", false)) {
feeder.pause(serverOutFact);
} else {
feeder.unpause();
}
});
cmds.put("skip", (q, w) -> {
int fromTrack = q.intValue("from_track", -1);
int trackIx = (fromTrack < 0 ? state.playingTrack().index : fromTrack) + q.intValue("step", 1);
Query.Onoff monomix = q.onoffValue("monomix");
if (trackIx >= tracks.length) {
// ignore forward from last track
w.append("{ \"restart\": false }");
} else {
w.append("{ \"restart\": true");
feeder.seek(Math.max(0, trackIx), 0, serverOutFact, monomix, w);
w.append("}");
}
});
cmds.put("seeka", (q, w) -> {
int trackIx = q.intValue("track", -1);
double time = q.doubleValue("time", 0);
Query.Onoff monomix = q.onoffValue("monomix");
w.append("{ \"restart\": true");
feeder.seek(trackIx, time, serverOutFact, monomix, w);
AudioStream stream = streamHandles.get(q.value("player_id", NO_PLAYER_ID));
if (stream != null) { stream.playedMillis(0); }
w.append("}");
});
cmds.put("seekr", (q, w) -> {
double time = state.playingTime() + q.doubleValue("time", 0);
if (Double.isNaN(time)) {
if (System.getProperty("klipspringer.debug") != null) { System.err.println("seekr when no track active"); }
w.append("{ \"restart\": false }");
return;
}
AudioStream stream = streamHandles.get(q.value("player_id", NO_PLAYER_ID));
Query.Onoff monomix = q.onoffValue("monomix");
if (stream != null) { stream.playedMillis(0); }
w.append("{ \"restart\": true");
feeder.seek(0, time, serverOutFact, monomix, w);
w.append("}");
});
}
protected void fetchStream(Query q, Device.Player.Factory streamFact) throws IOException {
AudioStream stream = streamHandles.get(q.value("player_id", NO_PLAYER_ID));
if (stream != null) { stream.close(); }
int trackIx = q.intValue("track", -1);
double time = q.doubleValue("time", 0);
Query.Onoff monomix = q.onoffValue("monomix");
feeder.seek(trackIx, time, streamFact, monomix, null);
}
}
Version: v4.3.2.2 (2026-05-16T17:03:34+02:00)
Raw file
Source code overview
Klipspringer home