mirror of
https://github.com/librespot-org/librespot.git
synced 2024-11-08 16:45:43 +00:00
Follow client setting to filter explicit tracks
- Don't load explicit tracks when the client setting forbids them - When a client switches explicit filtering on *while* playing an explicit track, immediately skip to the next track
This commit is contained in:
parent
2af34fc674
commit
0fdff0d3fd
5 changed files with 63 additions and 0 deletions
|
@ -746,12 +746,17 @@ impl SpircTask {
|
|||
_ => old_value,
|
||||
};
|
||||
self.session.set_user_attribute(key, new_value);
|
||||
|
||||
trace!(
|
||||
"Received attribute mutation, {} was {} is now {}",
|
||||
key,
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
|
||||
if key == "filter-explicit-content" && new_value == "1" {
|
||||
self.player.skip_explicit_content();
|
||||
}
|
||||
} else {
|
||||
trace!(
|
||||
"Received attribute mutation for {} but key was not found!",
|
||||
|
|
|
@ -26,6 +26,7 @@ pub struct AudioItem {
|
|||
pub duration: i32,
|
||||
pub availability: AudioItemAvailability,
|
||||
pub alternatives: Option<Tracks>,
|
||||
pub is_explicit: bool,
|
||||
}
|
||||
|
||||
impl AudioItem {
|
||||
|
|
|
@ -80,6 +80,7 @@ impl InnerAudioItem for Episode {
|
|||
duration: episode.duration,
|
||||
availability,
|
||||
alternatives: None,
|
||||
is_explicit: episode.is_explicit,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ impl InnerAudioItem for Track {
|
|||
duration: track.duration,
|
||||
availability,
|
||||
alternatives,
|
||||
is_explicit: track.is_explicit,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ enum PlayerCommand {
|
|||
SetSinkEventCallback(Option<SinkEventCallback>),
|
||||
EmitVolumeSetEvent(u16),
|
||||
SetAutoNormaliseAsAlbum(bool),
|
||||
SkipExplicitContent(),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -456,6 +457,10 @@ impl Player {
|
|||
pub fn set_auto_normalise_as_album(&self, setting: bool) {
|
||||
self.command(PlayerCommand::SetAutoNormaliseAsAlbum(setting));
|
||||
}
|
||||
|
||||
pub fn skip_explicit_content(&self) {
|
||||
self.command(PlayerCommand::SkipExplicitContent());
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Player {
|
||||
|
@ -478,6 +483,7 @@ struct PlayerLoadedTrackData {
|
|||
bytes_per_second: usize,
|
||||
duration_ms: u32,
|
||||
stream_position_pcm: u64,
|
||||
is_explicit: bool,
|
||||
}
|
||||
|
||||
enum PlayerPreload {
|
||||
|
@ -513,6 +519,7 @@ enum PlayerState {
|
|||
duration_ms: u32,
|
||||
stream_position_pcm: u64,
|
||||
suggested_to_preload_next_track: bool,
|
||||
is_explicit: bool,
|
||||
},
|
||||
Playing {
|
||||
track_id: SpotifyId,
|
||||
|
@ -526,6 +533,7 @@ enum PlayerState {
|
|||
stream_position_pcm: u64,
|
||||
reported_nominal_start_time: Option<Instant>,
|
||||
suggested_to_preload_next_track: bool,
|
||||
is_explicit: bool,
|
||||
},
|
||||
EndOfTrack {
|
||||
track_id: SpotifyId,
|
||||
|
@ -608,6 +616,7 @@ impl PlayerState {
|
|||
normalisation_data,
|
||||
stream_loader_controller,
|
||||
stream_position_pcm,
|
||||
is_explicit,
|
||||
..
|
||||
} => {
|
||||
*self = EndOfTrack {
|
||||
|
@ -620,6 +629,7 @@ impl PlayerState {
|
|||
bytes_per_second,
|
||||
duration_ms,
|
||||
stream_position_pcm,
|
||||
is_explicit,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -648,6 +658,7 @@ impl PlayerState {
|
|||
bytes_per_second,
|
||||
stream_position_pcm,
|
||||
suggested_to_preload_next_track,
|
||||
is_explicit,
|
||||
} => {
|
||||
*self = Playing {
|
||||
track_id,
|
||||
|
@ -661,6 +672,7 @@ impl PlayerState {
|
|||
stream_position_pcm,
|
||||
reported_nominal_start_time: None,
|
||||
suggested_to_preload_next_track,
|
||||
is_explicit,
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
|
@ -689,6 +701,7 @@ impl PlayerState {
|
|||
stream_position_pcm,
|
||||
reported_nominal_start_time: _,
|
||||
suggested_to_preload_next_track,
|
||||
is_explicit,
|
||||
} => {
|
||||
*self = Paused {
|
||||
track_id,
|
||||
|
@ -701,6 +714,7 @@ impl PlayerState {
|
|||
bytes_per_second,
|
||||
stream_position_pcm,
|
||||
suggested_to_preload_next_track,
|
||||
is_explicit,
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
|
@ -778,6 +792,16 @@ impl PlayerTrackLoader {
|
|||
audio.name, audio.spotify_uri
|
||||
);
|
||||
|
||||
let is_explicit = audio.is_explicit;
|
||||
if is_explicit {
|
||||
if let Some(value) = self.session.get_user_attribute("filter-explicit-content") {
|
||||
if &value == "1" {
|
||||
warn!("Track is marked as explicit, which client setting forbids.");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let audio = match self.find_available_alternative(audio).await {
|
||||
Some(audio) => audio,
|
||||
None => {
|
||||
|
@ -951,6 +975,7 @@ impl PlayerTrackLoader {
|
|||
bytes_per_second,
|
||||
duration_ms,
|
||||
stream_position_pcm,
|
||||
is_explicit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1518,6 +1543,7 @@ impl PlayerInternal {
|
|||
Instant::now() - Duration::from_millis(position_ms as u64),
|
||||
),
|
||||
suggested_to_preload_next_track: false,
|
||||
is_explicit: loaded_track.is_explicit,
|
||||
};
|
||||
} else {
|
||||
self.ensure_sink_stopped(false);
|
||||
|
@ -1533,6 +1559,7 @@ impl PlayerInternal {
|
|||
bytes_per_second: loaded_track.bytes_per_second,
|
||||
stream_position_pcm: loaded_track.stream_position_pcm,
|
||||
suggested_to_preload_next_track: false,
|
||||
is_explicit: loaded_track.is_explicit,
|
||||
};
|
||||
|
||||
self.send_event(PlayerEvent::Paused {
|
||||
|
@ -1674,6 +1701,7 @@ impl PlayerInternal {
|
|||
bytes_per_second,
|
||||
duration_ms,
|
||||
normalisation_data,
|
||||
is_explicit,
|
||||
..
|
||||
}
|
||||
| PlayerState::Paused {
|
||||
|
@ -1683,6 +1711,7 @@ impl PlayerInternal {
|
|||
bytes_per_second,
|
||||
duration_ms,
|
||||
normalisation_data,
|
||||
is_explicit,
|
||||
..
|
||||
} = old_state
|
||||
{
|
||||
|
@ -1693,6 +1722,7 @@ impl PlayerInternal {
|
|||
bytes_per_second,
|
||||
duration_ms,
|
||||
stream_position_pcm,
|
||||
is_explicit,
|
||||
};
|
||||
|
||||
self.preload = PlayerPreload::None;
|
||||
|
@ -1943,6 +1973,30 @@ impl PlayerInternal {
|
|||
PlayerCommand::SetAutoNormaliseAsAlbum(setting) => {
|
||||
self.auto_normalise_as_album = setting
|
||||
}
|
||||
|
||||
PlayerCommand::SkipExplicitContent() => {
|
||||
if let PlayerState::Playing {
|
||||
track_id,
|
||||
play_request_id,
|
||||
is_explicit,
|
||||
..
|
||||
}
|
||||
| PlayerState::Paused {
|
||||
track_id,
|
||||
play_request_id,
|
||||
is_explicit,
|
||||
..
|
||||
} = self.state
|
||||
{
|
||||
if is_explicit {
|
||||
warn!("Currently loaded track is explicit, which client setting forbids -- skipping to next track.");
|
||||
self.send_event(PlayerEvent::EndOfTrack {
|
||||
track_id,
|
||||
play_request_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
|
@ -2080,6 +2134,7 @@ impl fmt::Debug for PlayerCommand {
|
|||
.debug_tuple("SetAutoNormaliseAsAlbum")
|
||||
.field(&setting)
|
||||
.finish(),
|
||||
PlayerCommand::SkipExplicitContent() => f.debug_tuple("SkipExplicitContent").finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue