[Jellyfin] Fix how refresh is handled (#16013)
* [Jellyfin] Fix how refresh is handled --------- Signed-off-by: Miguel Álvarez <miguelwork92@gmail.com>
This commit is contained in:
parent
b33ebb8433
commit
d791e7900a
|
@ -4,7 +4,7 @@ This is the binding for [Jellyfin](https://jellyfin.org) the volunteer-built med
|
||||||
Stream to any device from your own server, with no strings attached.
|
Stream to any device from your own server, with no strings attached.
|
||||||
Your media, your server, your way.
|
Your media, your server, your way.
|
||||||
This binding allows connect to Jellyfin clients that supports remote control, it's build on top of the official Jellyfin kotlin sdk.
|
This binding allows connect to Jellyfin clients that supports remote control, it's build on top of the official Jellyfin kotlin sdk.
|
||||||
Compatible with Jellyfin servers from version 10.8.1, recommended 10.8.11.
|
Compatible with Jellyfin servers from version 10.8.1, recommended 10.8.13.
|
||||||
|
|
||||||
## Supported Things
|
## Supported Things
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,17 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jellyfin.sdk</groupId>
|
<groupId>org.jellyfin.sdk</groupId>
|
||||||
<artifactId>jellyfin-core-jvm</artifactId>
|
<artifactId>jellyfin-core-jvm</artifactId>
|
||||||
<version>1.4.4</version>
|
<version>1.4.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jellyfin.sdk</groupId>
|
<groupId>org.jellyfin.sdk</groupId>
|
||||||
<artifactId>jellyfin-api-jvm</artifactId>
|
<artifactId>jellyfin-api-jvm</artifactId>
|
||||||
<version>1.4.4</version>
|
<version>1.4.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jellyfin.sdk</groupId>
|
<groupId>org.jellyfin.sdk</groupId>
|
||||||
<artifactId>jellyfin-model-jvm</artifactId>
|
<artifactId>jellyfin-model-jvm</artifactId>
|
||||||
<version>1.4.4</version>
|
<version>1.4.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.ktor</groupId>
|
<groupId>io.ktor</groupId>
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class JellyfinClientHandler extends BaseThingHandler {
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
updateStatus(ThingStatus.UNKNOWN);
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
scheduler.execute(() -> refreshState());
|
scheduler.execute(this::refreshState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateStateFromSession(@Nullable SessionInfo session) {
|
public synchronized void updateStateFromSession(@Nullable SessionInfo session) {
|
||||||
|
@ -111,128 +111,30 @@ public class JellyfinClientHandler extends BaseThingHandler {
|
||||||
@Override
|
@Override
|
||||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
try {
|
try {
|
||||||
switch (channelUID.getId()) {
|
if (command instanceof RefreshType) {
|
||||||
case SEND_NOTIFICATION_CHANNEL:
|
refreshState();
|
||||||
if (command instanceof RefreshType) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendDeviceMessage(command);
|
|
||||||
break;
|
|
||||||
case MEDIA_CONTROL_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
refreshState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleMediaControlCommand(channelUID, command);
|
|
||||||
break;
|
|
||||||
case PLAY_BY_TERMS_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemSearch(command.toFullString(), PlayCommand.PLAY_NOW);
|
|
||||||
break;
|
|
||||||
case PLAY_NEXT_BY_TERMS_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemSearch(command.toFullString(), PlayCommand.PLAY_NEXT);
|
|
||||||
break;
|
|
||||||
case PLAY_LAST_BY_TERMS_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemSearch(command.toFullString(), PlayCommand.PLAY_LAST);
|
|
||||||
break;
|
|
||||||
case BROWSE_ITEM_BY_TERMS_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemSearch(command.toFullString(), null);
|
|
||||||
break;
|
|
||||||
case PLAY_BY_ID_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UUID itemUUID;
|
|
||||||
try {
|
|
||||||
itemUUID = parseItemUUID(command);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
logger.warn("Thing {}: Unable to parse item UUID in command {}.", thing.getUID(), command);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemById(itemUUID, PlayCommand.PLAY_NOW);
|
|
||||||
break;
|
|
||||||
case PLAY_NEXT_BY_ID_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
itemUUID = parseItemUUID(command);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
logger.warn("Thing {}: Unable to parse item UUID in command {}.", thing.getUID(), command);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemById(itemUUID, PlayCommand.PLAY_NEXT);
|
|
||||||
break;
|
|
||||||
case PLAY_LAST_BY_ID_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
itemUUID = parseItemUUID(command);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
logger.warn("Thing {}: Unable to parse item UUID in command {}.", thing.getUID(), command);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemById(itemUUID, PlayCommand.PLAY_LAST);
|
|
||||||
break;
|
|
||||||
case BROWSE_ITEM_BY_ID_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
itemUUID = parseItemUUID(command);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
logger.warn("Thing {}: Unable to parse item UUID in command {}.", thing.getUID(), command);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runItemById(itemUUID, null);
|
|
||||||
break;
|
|
||||||
case PLAYING_ITEM_SECOND_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
refreshState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (command.toFullString().equals(UnDefType.NULL.toFullString())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
seekToSecond(Long.parseLong(command.toFullString()));
|
|
||||||
break;
|
|
||||||
case PLAYING_ITEM_PERCENTAGE_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
refreshState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (command.toFullString().equals(UnDefType.NULL.toFullString())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
seekToPercentage(Integer.parseInt(command.toFullString()));
|
|
||||||
break;
|
|
||||||
case PLAYING_ITEM_ID_CHANNEL:
|
|
||||||
case PLAYING_ITEM_NAME_CHANNEL:
|
|
||||||
case PLAYING_ITEM_GENRES_CHANNEL:
|
|
||||||
case PLAYING_ITEM_SEASON_CHANNEL:
|
|
||||||
case PLAYING_ITEM_EPISODE_CHANNEL:
|
|
||||||
case PLAYING_ITEM_SERIES_NAME_CHANNEL:
|
|
||||||
case PLAYING_ITEM_SEASON_NAME_CHANNEL:
|
|
||||||
case PLAYING_ITEM_TYPE_CHANNEL:
|
|
||||||
case PLAYING_ITEM_TOTAL_SECOND_CHANNEL:
|
|
||||||
if (command instanceof RefreshType) {
|
|
||||||
refreshState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SEND_NOTIFICATION_CHANNEL -> sendDeviceMessage(command);
|
||||||
|
case MEDIA_CONTROL_CHANNEL -> handleMediaControlCommand(channelUID, command);
|
||||||
|
case PLAY_BY_TERMS_CHANNEL -> runItemSearch(command.toFullString(), PlayCommand.PLAY_NOW);
|
||||||
|
case PLAY_NEXT_BY_TERMS_CHANNEL -> runItemSearch(command.toFullString(), PlayCommand.PLAY_NEXT);
|
||||||
|
case PLAY_LAST_BY_TERMS_CHANNEL -> runItemSearch(command.toFullString(), PlayCommand.PLAY_LAST);
|
||||||
|
case BROWSE_ITEM_BY_TERMS_CHANNEL -> runItemSearch(command.toFullString(), null);
|
||||||
|
case PLAY_BY_ID_CHANNEL -> runItemById(parseItemUUID(command), PlayCommand.PLAY_NOW);
|
||||||
|
case PLAY_NEXT_BY_ID_CHANNEL -> runItemById(parseItemUUID(command), PlayCommand.PLAY_NEXT);
|
||||||
|
case PLAY_LAST_BY_ID_CHANNEL -> runItemById(parseItemUUID(command), PlayCommand.PLAY_LAST);
|
||||||
|
case BROWSE_ITEM_BY_ID_CHANNEL -> runItemById(parseItemUUID(command), null);
|
||||||
|
case PLAYING_ITEM_SECOND_CHANNEL -> seekToSecond(command);
|
||||||
|
case PLAYING_ITEM_PERCENTAGE_CHANNEL -> seekToPercentage(command);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException numberFormatException) {
|
||||||
|
logger.warn("NumberFormatException error while running channel {}: {}", channelUID.getId(),
|
||||||
|
numberFormatException.getMessage());
|
||||||
|
} catch (IllegalArgumentException illegalArgumentException) {
|
||||||
|
logger.warn("IllegalArgumentException error while running channel {}: {}", channelUID.getId(),
|
||||||
|
illegalArgumentException.getMessage());
|
||||||
} catch (SyncCallback.SyncCallbackError syncCallbackError) {
|
} catch (SyncCallback.SyncCallbackError syncCallbackError) {
|
||||||
logger.warn("Unexpected error while running channel {}: {}", channelUID.getId(),
|
logger.warn("Unexpected error while running channel {}: {}", channelUID.getId(),
|
||||||
syncCallbackError.getMessage());
|
syncCallbackError.getMessage());
|
||||||
|
@ -241,10 +143,14 @@ public class JellyfinClientHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID parseItemUUID(Command command) throws NumberFormatException {
|
private UUID parseItemUUID(Command command) throws IllegalArgumentException {
|
||||||
var itemId = command.toFullString().replace("-", "");
|
try {
|
||||||
return new UUID(new BigInteger(itemId.substring(0, 16), 16).longValue(),
|
var itemId = command.toFullString().replace("-", "");
|
||||||
new BigInteger(itemId.substring(16), 16).longValue());
|
return new UUID(new BigInteger(itemId.substring(0, 16), 16).longValue(),
|
||||||
|
new BigInteger(itemId.substring(16), 16).longValue());
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
throw new IllegalArgumentException("Unable to parse item UUID in command " + command.toFullString() + ".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -586,17 +492,27 @@ public class JellyfinClientHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void seekToPercentage(int percentage) throws SyncCallback.SyncCallbackError, ApiClientException {
|
private void seekToPercentage(Command command)
|
||||||
|
throws NumberFormatException, SyncCallback.SyncCallbackError, ApiClientException {
|
||||||
|
if (command.toFullString().equals(UnDefType.NULL.toFullString())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (lastRunTimeTicks == 0L) {
|
if (lastRunTimeTicks == 0L) {
|
||||||
logger.warn("Can't seek missing RunTimeTicks info");
|
logger.warn("Can't seek missing RunTimeTicks info");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int percentage = Integer.parseInt(command.toFullString());
|
||||||
var seekPositionTick = Math.round(((float) lastRunTimeTicks) * ((float) percentage / 100.0));
|
var seekPositionTick = Math.round(((float) lastRunTimeTicks) * ((float) percentage / 100.0));
|
||||||
logger.debug("Seek to {}%: {} of {}", percentage, seekPositionTick, lastRunTimeTicks);
|
logger.debug("Seek to {}%: {} of {}", percentage, seekPositionTick, lastRunTimeTicks);
|
||||||
seekToTick(seekPositionTick);
|
seekToTick(seekPositionTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void seekToSecond(long second) throws SyncCallback.SyncCallbackError, ApiClientException {
|
private void seekToSecond(Command command)
|
||||||
|
throws NumberFormatException, SyncCallback.SyncCallbackError, ApiClientException {
|
||||||
|
if (command.toFullString().equals(UnDefType.NULL.toFullString())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long second = Long.parseLong(command.toFullString());
|
||||||
long seekPositionTick = second * 10000000L;
|
long seekPositionTick = second * 10000000L;
|
||||||
logger.debug("Seek to second {}: {} of {}", second, seekPositionTick, lastRunTimeTicks);
|
logger.debug("Seek to second {}: {} of {}", second, seekPositionTick, lastRunTimeTicks);
|
||||||
seekToTick(seekPositionTick);
|
seekToTick(seekPositionTick);
|
||||||
|
|
Loading…
Reference in New Issue