Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow changing of volume in different steps #629

Merged
merged 4 commits into from
Dec 8, 2024
Merged

Conversation

DOD-101
Copy link
Contributor

@DOD-101 DOD-101 commented Dec 8, 2024

Resolves #616

This change implements what was requested in #616, but would require users to re-write their keymap.toml.

The new format for keymap.tomlwould be:

[[keymaps]]
key_sequence = "+"
command = { type = "VolumeChange", args = { offset = 1 } }

[[keymaps]]
key_sequence = "-"
command = { type = "VolumeChange", args = { offset = -1 } }

[[keymaps]]
key_sequence = "n"
command = { type = "NextTrack" }

I'm looking for input on whether this is a good idea to implement this way. Or if an alternative would be better.

There is also the option of leaving the configuration syntax as is and setting the offset like this:

[[keymaps]]
key_sequence = "+"
command = "VolumeChange 1"

And this approach has some advantages and disadvantages.

For one, the config format for the other commands wouldn't change, but as far as I can tell I would have to write some custom deserialization logic, since TOML doesn't support this syntax out of the box. And any future commands, which have arguments, would need to do the same.

Personally, I don't have a preference either way.

@DOD-101
Copy link
Contributor Author

DOD-101 commented Dec 8, 2024

So I went ahead a wrote the deserialize function needed for the alternative syntax. It's not pretty, but it's a proof of concept.

I will say that I don't have any real experience with serde, so there might be a far better way of doing this:

impl<'de> Deserialize<'de> for Command {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let input = String::deserialize(deserializer)?;
        let parts: Vec<&str> = input.split_whitespace().collect();

        let variant_name = parts[0];

        match variant_name {
            "VolumeChange" => {
                let offset = parts
                    .get(1)
                    .ok_or(serde::de::Error::custom("No offset Provided"))?
                    .parse::<i32>()
                    .map_err(|_| serde::de::Error::custom("Failed to parse offset"))?;
                Ok(Command::VolumeChange { offset })
            }
            "None" => Ok(Command::None),
            "NextTrack" => Ok(Command::NextTrack),
            "PreviousTrack" => Ok(Command::PreviousTrack),
            "ResumePause" => Ok(Command::ResumePause),
            "PlayRandom" => Ok(Command::PlayRandom),
            "Repeat" => Ok(Command::Repeat),
            "ToggleFakeTrackRepeatMode" => Ok(Command::ToggleFakeTrackRepeatMode),
            "Shuffle" => Ok(Command::Shuffle),
            "Mute" => Ok(Command::Mute),
            "SeekForward" => Ok(Command::SeekForward),
            "SeekBackward" => Ok(Command::SeekBackward),
            "Quit" => Ok(Command::Quit),
            "ClosePopup" => Ok(Command::ClosePopup),
            #[cfg(feature = "streaming")]
            "RestartIntegratedClient" => Ok(Command::RestartIntegratedClient),
            "SelectNextOrScrollDown" => Ok(Command::SelectNextOrScrollDown),
            "SelectPreviousOrScrollUp" => Ok(Command::SelectPreviousOrScrollUp),
            "PageSelectNextOrScrollDown" => Ok(Command::PageSelectNextOrScrollDown),
            "PageSelectPreviousOrScrollUp" => Ok(Command::PageSelectPreviousOrScrollUp),
            "SelectFirstOrScrollToTop" => Ok(Command::SelectFirstOrScrollToTop),
            "SelectLastOrScrollToBottom" => Ok(Command::SelectLastOrScrollToBottom),
            "ChooseSelected" => Ok(Command::ChooseSelected),
            "JumpToCurrentTrackInContext" => Ok(Command::JumpToCurrentTrackInContext),
            "RefreshPlayback" => Ok(Command::RefreshPlayback),
            "ShowActionsOnSelectedItem" => Ok(Command::ShowActionsOnSelectedItem),
            "ShowActionsOnCurrentTrack" => Ok(Command::ShowActionsOnCurrentTrack),
            "AddSelectedItemToQueue" => Ok(Command::AddSelectedItemToQueue),
            "FocusNextWindow" => Ok(Command::FocusNextWindow),
            "FocusPreviousWindow" => Ok(Command::FocusPreviousWindow),
            "SwitchTheme" => Ok(Command::SwitchTheme),
            "SwitchDevice" => Ok(Command::SwitchDevice),
            "Search" => Ok(Command::Search),
            "BrowseUserPlaylists" => Ok(Command::BrowseUserPlaylists),
            "BrowseUserFollowedArtists" => Ok(Command::BrowseUserFollowedArtists),
            "BrowseUserSavedAlbums" => Ok(Command::BrowseUserSavedAlbums),
            "CurrentlyPlayingContextPage" => Ok(Command::CurrentlyPlayingContextPage),
            "TopTrackPage" => Ok(Command::TopTrackPage),
            "RecentlyPlayedTrackPage" => Ok(Command::RecentlyPlayedTrackPage),
            "LikedTrackPage" => Ok(Command::LikedTrackPage),
            #[cfg(feature = "lyric-finder")]
            "LyricPage" => Ok(Command::LyricPage),
            "LibraryPage" => Ok(Command::LibraryPage),
            "SearchPage" => Ok(Command::SearchPage),
            "BrowsePage" => Ok(Command::BrowsePage),
            "Queue" => Ok(Command::Queue),
            "OpenCommandHelp" => Ok(Command::OpenCommandHelp),
            "PreviousPage" => Ok(Command::PreviousPage),
            "OpenSpotifyLinkFromClipboard" => Ok(Command::OpenSpotifyLinkFromClipboard),
            "SortTrackByTitle" => Ok(Command::SortTrackByTitle),
            "SortTrackByArtists" => Ok(Command::SortTrackByArtists),
            "SortTrackByAlbum" => Ok(Command::SortTrackByAlbum),
            "SortTrackByDuration" => Ok(Command::SortTrackByDuration),
            "SortTrackByAddedDate" => Ok(Command::SortTrackByAddedDate),
            "ReverseTrackOrder" => Ok(Command::ReverseTrackOrder),
            "MovePlaylistItemUp" => Ok(Command::MovePlaylistItemUp),
            "MovePlaylistItemDown" => Ok(Command::MovePlaylistItemDown),
            "CreatePlaylist" => Ok(Command::CreatePlaylist),
            _ => Err(serde::de::Error::custom(format!(
                "Unknown variant: {}",
                variant_name
            ))),
        }
    }
}

@DOD-101 DOD-101 marked this pull request as ready for review December 8, 2024 20:10
@@ -355,6 +358,8 @@ impl Command {
Self::MovePlaylistItemUp => "move playlist item up one position",
Self::MovePlaylistItemDown => "move playlist item down one position",
Self::CreatePlaylist => "create a new playlist",
_ => unreachable!(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_ => unreachable!(),
Self::VolumeChange { .. } => unreachable!(),

enum handling is preferred to be explicit to avoid misuse, e.g. forgetting to handle new variants

docs/config.md Outdated Show resolved Hide resolved
@aome510 aome510 merged commit ff4eaac into aome510:master Dec 8, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow changing step for volume up/down
2 participants