-
Notifications
You must be signed in to change notification settings - Fork 638
Events
With librespot --onevent=/path/to/my/event/script/program
users can subscribe to non-blocking events. By also passing emit-sink-events
users can also subscribe to blocking sink events with the same /script/program. The purpose of blocking sink events is to block the player thread to allow for something to be done before the sink is opened or after it is closed.
The type of script/program you use to handle events is completely up to you, librespot
simply runs the script/program every time an event is fired and passes events via environment variables.
PLAYER_EVENT
will contain the name of the Event. Additional environment variables will follow depending on the Event.
The mapping is as follows:
Non-blocking Events
Non-blocking events are non-blocking in every sense. They do not block librespot
threads in any way and the event script/program is run in it's own separate thread for each and every event. librespot
's event handler does not wait for event scripts/programs to exit before it fires the next event. This can lead to data race situations if the events take a variable amount of time for the script/program to process. It is up to the user to keep track of event sequencing. This has been fixed in dev.
Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | changed |
Name of the Event |
OLD_TRACK_ID | Spotify Track ID | ID of the previous Track |
TRACK_ID | Spotify Track ID | ID of the new Track |
Started
Key | Value | Description |
---|---|---|
PLAYER_EVENT | started |
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
Stopped
Key | Value | Description |
---|---|---|
PLAYER_EVENT | stopped |
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
Playing
Key | Value | Description |
---|---|---|
PLAYER_EVENT | playing |
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
DURATION_MS | Milliseconds | Duration in ms |
POSITION_MS | Milliseconds | Position in ms |
Paused
Key | Value | Description |
---|---|---|
PLAYER_EVENT | paused |
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
DURATION_MS | Milliseconds | Duration in ms |
POSITION_MS | Milliseconds | Position in ms |
Preloading
Key | Value | Description |
---|---|---|
PLAYER_EVENT | preloading |
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
Volume Set
Key | Value | Description |
---|---|---|
PLAYER_EVENT | volume_set |
Name of the Event |
VOLUME | volume | Volume 0 - 65535 |
Blocking Events
Blocking events are blocking in every sense. They block librespot
's player thread and also therefore block themselves. librespot
's player thread will not unblock until the event script/program exits. Blocking events will not be fired by default for that reason. Use blocking events with care.
Running
Key | Value | Description |
---|---|---|
PLAYER_EVENT | sink |
Name of the Event |
SINK_STATUS | running |
The sink is about to be opened |
Temporarily Closed (Transient State)
Key | Value | Description |
---|---|---|
PLAYER_EVENT | sink |
Name of the Event |
SINK_STATUS | temporarily_closed |
The sink has closed, but more than likely will be reopened very shortly |
Closed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | sink |
Name of the Event |
SINK_STATUS | closed |
The sink has closed |
Example
Here is an example Python skeleton to further illustrate:
#!/usr/bin/python3
import os
# Non-blocking Events
if os.environ['PLAYER_EVENT'] == 'changed':
old_track_id = os.environ['OLD_TRACK_ID']
new_track_id = os.environ['TRACK_ID']
# do stuff
elif os.environ['PLAYER_EVENT'] == 'started':
track_id = os.environ['TRACK_ID']
# do suff
elif os.environ['PLAYER_EVENT'] == 'stopped':
track_id = os.environ['TRACK_ID']
# do stuff
elif os.environ['PLAYER_EVENT'] == 'playing':
track_id = os.environ['TRACK_ID']
track_duration_ms = os.environ['DURATION_MS']
track_position_ms = os.environ['POSITION_MS']
# do stuff
elif os.environ['PLAYER_EVENT'] == 'paused':
track_id = os.environ['TRACK_ID']
track_duration_ms = os.environ['DURATION_MS']
track_position_ms = os.environ['POSITION_MS']
# do stuff
elif os.environ['PLAYER_EVENT'] == 'preloading':
track_id = os.environ['TRACK_ID']
# do stuff
elif os.environ['PLAYER_EVENT'] == 'volume_set':
volume = os.environ['VOLUME']
# do stuff
# Blocking Events
elif os.environ['PLAYER_EVENT'] == 'sink':
status = os.environ['SINK_STATUS']
if status == 'running':
# do stuff
elif status == 'temporarily_closed':
# do stuff
elif status == 'closed':
# do stuff
Non-blocking Events
Non-blocking events do not block librespot
threads but are buffered and blocking to themselves so that subsequent events are not fired until the event script/program exits after processing the previous event to help guarantee that event script/program do not process events out of order.
Track Changed
Track Changed has Common Fields shared by both Tracks and Episodes and Fields unique to Tracks and Episodes.
Common Fields
Key | Value | Description |
---|---|---|
PLAYER_EVENT | track_changed |
Name of the Event |
ITEM_TYPE |
Track / Episode
|
Track or Episode |
TRACK_ID | Uri | Uri of the Track |
URI | Spotify Track ID | ID of the Track |
NAME | Name | Name of the Track |
DURATION_MS | Milliseconds | Duration in ms |
IS_EXPLICIT | True/False | If the Track is Explicit |
LANGUAGE | Languages |
\n separated list of Languages |
COVERS | Cover urls |
\n separated list of Cover urls from largest to smallest in size |
Track Item Type Specific Fields
Key | Value | Description |
---|---|---|
NUMBER | Track Number | Number of the Track as it appears on the album |
DISC_NUMBER | Disc Number | Disc Number of the Track as it appears on the album |
POPULARITY | Popularity | Popularity of the Track 0 - 100 |
ALBUM | Album | Album the Track appears on |
ARTISTS | Artists |
\n separated list of the artists that appear on the Track |
ALBUM_ARTISTS | Album Artists |
\n separated list of the artists of the album |
Episode Item Type Specific Fields
Key | Value | Description |
---|---|---|
SHOW_NAME | Show Name | Name of the Show |
PUBLISH_TIME | Unix Timestamp | Unix Timestamp of the Publish Time |
DESCRIPTION | Description | Description of the Show/Episode |
Session Connected / Session Disconnected
These Events all share common fields, just PLAYER_EVENT
is different.
Key | Value | Description |
---|---|---|
PLAYER_EVENT |
session_connected / session_disconnected
|
Name of the Event |
USER_NAME | User Name | Session User Name (really an ID not a display name) |
CONNECTION_ID | Connection ID | Session Connection ID |
Session Client Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | session_client_changed |
Name of the Event |
CLIENT_ID | Client ID | ID of the Client |
CLIENT_NAME | Client Name | Name of the Client |
CLIENT_BRAND_NAME | Client Brand Name | Brand Name of the Client |
CLIENT_MODEL_NAME | Client Model Name | Model Name of the Client |
Playing / Paused / Seeked / Position Correction
These Events all share common fields, just PLAYER_EVENT
is different.
Key | Value | Description |
---|---|---|
PLAYER_EVENT |
playing / paused / seeked / position_correction
|
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
POSITION_MS | Milliseconds | Position in ms |
Unavailable / End of Track / Preload Next / Preloading / Loading / Stopped
These Events all share common fields, just PLAYER_EVENT
is different.
Key | Value | Description |
---|---|---|
PLAYER_EVENT |
unavailable / end_of_track / preload_next / preloading / loading / stopped
|
Name of the Event |
TRACK_ID | Spotify Track ID | ID of the Track |
Volume Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | volume_changed |
Name of the Event |
VOLUME | volume | Volume 0 - 65535 |
Shuffle Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | shuffle_changed |
Name of the Event |
SHUFFLE | True/False | State of the Shuffle toggle |
Repeat Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | repeat_changed |
Name of the Event |
REPEAT | True/False | State of the Repeat toggle |
Auto Play Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | auto_play_changed |
Name of the Event |
AUTO_PLAY | True/False | State of the Auto Play toggle |
Filter Explicit Content Changed
Key | Value | Description |
---|---|---|
PLAYER_EVENT | filter_explicit_content_changed |
Name of the Event |
FILTER | True/False | State of the Filter Explicit Content toggle |
Blocking Events
Blocking Events and behavior have not changed and are identical to that of Released - master
.
Example
An example non-blocking Event Python script can be found Here.
Refer to the above Released - master
example for Blocking Events.