Update documentation for 1.5

This commit is contained in:
Niels van Velzen 2024-06-01 13:34:33 +02:00 committed by Niels van Velzen
parent 72d54e6ca0
commit 5d1bb6208f
3 changed files with 53 additions and 140 deletions

View File

@ -24,7 +24,7 @@ val api = jellyfin.createApi(
Change the token in an existing API client instance like so:
```kotlin
api.accessToken = "02a7174a4d1843448b6d177d8288efd0"
api.update(accessToken = "02a7174a4d1843448b6d177d8288efd0")
```
## Password login
@ -43,7 +43,7 @@ try {
)
// Use access token in api instance
api.accessToken = authenticationResult.accessToken
api.update(accessToken = authenticationResult.accessToken)
// Print session information
println(authenticationResult.sessionInfo)
@ -70,19 +70,19 @@ the new one.
The Quick Connect functionality may be disabled by a server. In those cases the server responds with an HTTP 401
response. You can check if QuickConnect is enabled first or deal with it when trying to use it.
To start a Quick Connect session you need to request a Quick Connect code with the initiate function. This returns a
state object which can be updated by calling the connect method.
To start a Quick Connect session you need to request a Quick Connect code with the initiateQuickConnect function. This
returns a state object which can be updated by calling the getQuickConnectState method.
```kotlin
val api = jellyfin.createApi(/* .. */)
// Check if Quick Connect is enabled (this is optional)
val enabled by api.quickConnectApi.getEnabled()
val enabled by api.quickConnectApi.getQuickConnectEnabled()
if (!enabled) println("QuickConnect is disabled in the server!")
// Create a Quick Connect session and store the state
try {
var quickConnectState by api.quickConnectApi.initiate()
val quickConnectState by api.quickConnectApi.initiateQuickConnect()
} catch (err: InvalidStatusException) {
if (err.status == 401) {
// Quick Connect is disabled
@ -99,13 +99,12 @@ The Quick Connect state contains a few values that are of interest:
- The `code` is for the user to input in a different app
The next step is to show the code to the user. Depending on your app you might want to either show a "next" button to
press
when the user authorized the app or automatically update the Quick Connect state. In the latter example we recommend
updating every 5 seconds.
press when the user authorized the app or automatically update the Quick Connect state. In the latter example we
recommend updating every 5 seconds.
```kotlin
// Update the Quick Connect session state
quickConnectState = api.quickConnectApi.connect(
quickConnectState = api.quickConnectApi.getQuickConnectState(
secret = quickConnectState.secret,
)
```
@ -119,7 +118,7 @@ val authenticationResult by api.userApi.authenticateWithQuickConnect(
)
// Use access token in api instance
api.accessToken = authenticationResult.accessToken
api.update(accessToken = authenticationResult.accessToken)
// Print session information
println(authenticationResult.sessionInfo)

View File

@ -106,7 +106,7 @@ try {
)
// Use access token in api instance
api.accessToken = authenticationResult.accessToken
api.update(accessToken = authenticationResult.accessToken)
// Print session information
println(authenticationResult.sessionInfo)
@ -122,9 +122,7 @@ Jellyfin uses WebSockets to communicate events like library changes and activiti
used with the SocketApi.
```kotlin
val instance = api.ws()
instance.addGlobalListener { message ->
api.webSocket.subscribeAll().collect { message ->
println(message)
}
```
@ -162,4 +160,4 @@ val recommended = jellyfin.discovery.getRecommendedServers(candidates, Recommend
and series.
- [Homedia](https://github.com/valmnt/homedia) provides a native user interface for Android TV using Jetpack Compose.
_Want to add your project? We'd love to know about it, open an issue or create pull request!_
_Want to add your project? We'd love to know about it, please open a pull request to add it!_

View File

@ -1,92 +1,77 @@
# Using WebSockets
Added in v1.2.0, the new WebSocket implementation can be used to interact with the Jellyfin WebSocket server. This API
is not supported with the Java language because it heavily relies on coroutines and inline functions.
The WebSocket API can be used to interact with the Jellyfin WebSocket server. Get started by creating a new
authenticated API instance using the `createApi` function in the Jellyfin class.
Get started by creating a new authenticated API instance using the `createApi` function in the Jellyfin class.
Listening the WebSocket messages is done using subscriptions. Whenever one or multiple subscriptions are active the
WebSocket will automatically connect to the server. Credentials changes via the `update()` function will cause the
WebSocket to reconnect. There is a single WebSocket API for each ApiClient.
```kotlin
// Create an API instance
val api = jellyfin.createApi(baseUrl = "https://demo.jellyfin.org/stable/")
```
## Connecting
The socket connection is managed by an "instance". You can have multiple of these instances at the same time. However,
it is recommended to use a single instance during the lifecycle of your application. Use the `ws()`
function from the ApiClient class to create a new instance.
```kotlin
val instance = api.ws()
```
You can close an instance when it's no longer in use with the `stop()` function.
```kotlin
instance.stop()
// Create a subscription for WebSocket all messages
api.webSocket.subscribeAll().collect { message ->
println(message)
}
```
## Updating credentials
An instance does not automatically refresh credentials. You'll need to manually refresh the instance when the access
token, server or device info change. Use the `updateCredentials()` function to apply these changes. The instance
automatically reconnects when required.
The WebSocket connection will reconnect when the server URL, access token, client information of device information
changes. All existing subscriptions stay active and automatically switch to the new credentials.
## Subscribe to messages
Subscriptions are used to receive the various types of websocket messages. A connection is automatically started and/or
closed depending on the availability of subscriptions. Multiple extension functions can be used to create a
subscription. They all return a flow that emits each message as soon as it is received.
## Subscribe to specific messages
Use the `subscribe<T>()` function to create a listener that receives a single message type.
```kotlin
instance.updateCredentials()
```
## Listen for messages
Listeners are used to receive the various types of websocket messages. A connection is automatically started and/or
closed depending on the active listeners. Multiple helper functions can be used to register a listener. They all return
a `SocketListener` object that can be used to remove the listener later with the `removeListener()` function on the
instance or the `stop()` on the listener.
## Listen for specific messages
Use the `addListener()` function to create a listener that receives a single type.
```kotlin
instance.addListener<UserDataChangedMessage> { message ->
api.webSocket.subscribe<UserDataChangedMessage>().collect { message ->
// type of message is UserDataChangedMessage
println("Received a message: $message")
}
```
## Listen for all messages
## Subscribe to all messages
If you want to listen for all types of messages instead. Use the `addGlobalListener` function.
Use the `subscribeAll` function if you want to subscribe to all types of messages instead. This is not recommended if
you only want to receive a subset of message types.
```kotlin
instance.addGlobalListener { message ->
// type of message is IncomingSocketMessage
api.webSocket.subscribeAll().collect { message ->
// type of message is OutboundWebSocketMessage
println("Received a message: $message")
}
```
## Listen for grouped message types
## Subscribe to grouped message types
Some incoming messages are used for multiple kinds of information. These are the general, play state and SyncPlay
commands. To filter the types of commands there are a few helper functions available. All of them support a "commands"
parameter to define the message types to receive. All types will be sent when the commands parameter is omitted. This is
the same behavior as using `addListener`.
Some incoming messages are used for multiple kinds of information. These are the general commands, play state and
SyncPlay command messages. To filter the types of commands there are extensions functions available. All of them support
filtering for one or multiple commands to receive. All types will be sent when the commands parameter is omitted. This is
the same behavior as using the `subscribe<T>` function.
```kotlin
instance.addGeneralCommandsListener(
commands = setOf(GeneralCommandType.DISPLAY_MESSAGE)
) { message ->
api.webSocket.subscribeGeneralCommand(GeneralCommandType.DISPLAY_MESSAGE).collect { message ->
// type of message is GeneralCommandMessage
println("Received a message: $message")
}
instance.addPlayStateCommandsListener(
api.webSocket.subscribePlayStateCommands(
commands = setOf(PlaystateCommand.NEXT_TRACK, PlaystateCommand.PREVIOUS_TRACK)
) { message ->
// type of message is PlayStateMessage
).collect { message ->
// type of message is PlaystateMessage
println("Received a message: $message")
}
instance.addSyncPlayCommandsListener(
api.webSocket.subscribeSyncPlayCommands(
commands = setOf(SendCommandType.PAUSE, SendCommandType.UNPAUSE)
) { message ->
// type of message is SyncPlayCommandMessage
@ -94,79 +79,10 @@ instance.addSyncPlayCommandsListener(
}
```
## Advanced listeners
All previously mentioned functions to add listeners use the `addListenerDefinition` function under the hood. This
function is not recommended being used directly. Use the other functions instead. The function receives a listener
definition.
An example for listening to both LibraryChangedMessage and UserDataChangedMessage messages:
```kotlin
instance.addListenerDefinition(
SocketListenerDefinition(
subscribesTo = emptySet(),
filterTypes = setOf(LibraryChangedMessage::class, UserDataChangedMessage::class),
stopOnCredentialsChange = false,
listener = { message ->
// type of message is IncomingSocketMessage
println("Received a message: $message")
}
)
)
```
## Sending messages
The Jellyfin server uses HTTP endpoints, mostly in the SessionApi, to manipulate state. The only messages send by a
client are to enable subscriptions. These subscriptions are automatically managed by the SDK. The `publish()` function
can still be used if you need to send your own messages. The function receives a `OutgoingSocketMessage` type and sends
it to the server.
```kotlin
instance.publish(SessionsStartMessage())
```
> **Note**: Do not send start and stop messages manually. This can confuse the SDK and cause unknown behavior.
## Message Types
The following messages types are supported in the SDK.
### Incoming
- GeneralCommandMessage
- UserDataChangedMessage
- SessionsMessage
- PlayMessage
- SyncPlayCommandMessage
- SyncPlayGroupUpdateMessage
- PlayStateMessage
- RestartRequiredMessage
- ServerShuttingDownMessage
- ServerRestartingMessage
- LibraryChangedMessage
- UserDeletedMessage
- UserUpdatedMessage
- SeriesTimerCreatedMessage
- TimerCreatedMessage
- SeriesTimerCancelledMessage
- TimerCancelledMessage
- RefreshProgressMessage
- ScheduledTaskEndedMessage
- PackageInstallationCancelledMessage
- PackageInstallationFailedMessage
- PackageInstallationCompletedMessage
- PackageInstallingMessage
- PackageUninstalledMessage
- ActivityLogEntryMessage
- ScheduledTasksInfoMessage
### Outgoing
- ActivityLogEntryStartMessage and ActivityLogEntryStopMessage
- SessionsStartMessage and SessionsStopMessage
- ScheduledTasksInfoStartMessage and ScheduledTasksInfoStopMessage
The SDK does not expose any functionality to send messages. Publishing messages is only used to keep the connection
alive or to request for certain message types to be sent. This is all managed by the SDK.
## Sample usage