{ config, nixosConfig, lib, mylib, pkgs, ... }: let inherit (config.modules) rmpc color; in { options.modules.rmpc = import ./options.nix {inherit lib mylib;}; config = lib.mkIf rmpc.enable { assertions = [ { assertion = config.services.mpd.enable; message = "Enabling rmpc requires mpd!"; } ]; programs.rmpc.enable = true; home.packages = with pkgs; [ cava python313Packages.syncedlyrics ]; home.file = let themeName = "chriphost"; in { # TODO: notify-send song title or sth. # TODO: status bar colors (the thing that pops up in the progress/seeking bar sometimes) # TODO: allow adding items to playlists not only from the queue view ".config/rmpc/config.ron".text = '' #![enable(implicit_some)] #![enable(unwrap_newtypes)] #![enable(unwrap_variant_newtypes)] ( address: "127.0.0.1:${builtins.toString config.services.mpd.network.port}", password: None, theme: "${themeName}", cache_dir: None, on_song_change: None, volume_step: 5, max_fps: 30, scrolloff: 0, wrap_navigation: false, enable_mouse: true, enable_config_hot_reload: true, status_update_interval_ms: 1000, rewind_to_start_sec: 30, lyrics_dir: "${config.home.homeDirectory}/Music", // Keep this on false, otherwise queue changes will be applied to the current playlist reflect_changes_to_playlist: false, select_current_song_on_change: false, browser_song_sort: [Disc, Track, Artist, Title], directories_sort: SortFormat(group_by_type: true, reverse: false), album_art: ( method: Auto, max_size_px: (width: 1200, height: 1200), disabled_protocols: ["http://", "https://"], vertical_align: Center, horizontal_align: Center, ), search: ( case_sensitive: false, mode: Contains, tags: [ (value: "any", label: "Any Tag"), (value: "artist", label: "Artist"), (value: "album", label: "Album"), (value: "albumartist", label: "Album Artist"), (value: "title", label: "Title"), (value: "filename", label: "Filename"), (value: "genre", label: "Genre"), ], ), artists: ( album_display_mode: SplitByDate, album_sort_by: Date, ), tabs: [ ( name: "Queue (1)", pane: Split( borders: "NONE", direction: Horizontal, panes: [ // Left Column (Queue + Cava) ( size: "70%", borders: "NONE", pane: Split( direction: Vertical, panes: [ ( size: "75%", borders: "ALL", pane: Pane(Queue), ), ( size: "25%", borders: "ALL", pane: Pane(Cava), ) ] ) ), // Right Column (AlbumArt + Lyrics) ( size: "30%", borders: "NONE", pane: Split( direction: Vertical, panes: [ ( size: "75%", borders: "ALL", pane: Pane(AlbumArt), ), ( size: "25%", borders: "ALL", pane: Pane(Lyrics), ), ] ), ), ] ), ), ( name: "Albums (2)", pane: Pane(Albums), ), ( name: "Album Artists (3)", pane: Pane(AlbumArtists), ), ( name: "Artists (4)", pane: Pane(Artists), ), ( name: "Playlists (5)", pane: Pane(Playlists), ), // ( // name: "Directories (6)", // pane: Pane(Directories), // ), ( name: "Search (6)", pane: Pane(Search), ), // ( // name: "Visualizer (8)", // pane: Pane(Cava), // ), ], cava: ( framerate: 60, // default 60 autosens: true, // default true sensitivity: 100, // default 100 lower_cutoff_freq: 50, // not passed to cava if not provided higher_cutoff_freq: 10000, // not passed to cava if not provided input: ( method: Fifo, source: "/tmp/mpd.fifo", sample_rate: 44100, channels: 2, sample_bits: 16, ), smoothing: ( noise_reduction: 77, // default 77 monstercat: false, // default false waves: false, // default false ), // this is a list of floating point numbers thats directly passed to cava // they are passed in order that they are defined eq: [], ), keybinds: ( global: { "q": Quit, "p": TogglePause, "s": Stop, ">": NextTrack, "<": PreviousTrack, ",": VolumeDown, ".": VolumeUp, ":": CommandMode, "": NextTab, "": PreviousTab, "1": SwitchToTab("Queue (1)"), "2": SwitchToTab("Albums (2)"), "3": SwitchToTab("Album Artists (3)"), "4": SwitchToTab("Artists (4)"), "5": SwitchToTab("Playlists (5)"), // "6": SwitchToTab("Directories (6)"), "6": SwitchToTab("Search (6)"), // "8": SwitchToTab("Visualizer (8)"), "?": ShowHelp, "z": ToggleRepeat, "x": ToggleRandom, "c": ToggleConsumeOnOff, // Skip OneShot mode "v": ToggleSingleOnOff, // Skip OneShot mode "f": SeekForward, "b": SeekBack, "u": Update, "U": Rescan, "I": ShowCurrentSongInfo, "O": ShowOutputs, "P": ShowDecoders, "R": AddRandom, }, navigation: { "k": Up, "j": Down, "h": Left, "l": Right, "": Up, "": Down, "": Left, "": Right, "g": Top, "G": Bottom, "": UpHalf, "": DownHalf, "J": MoveDown, "K": MoveUp, "": PaneUp, "": PaneDown, "": PaneLeft, "": PaneRight, "N": PreviousResult, "a": Add, "A": AddAll, "r": Rename, "n": NextResult, "": Select, "": InvertSelection, "": Confirm, "i": FocusInput, "/": EnterSearch, "": Close, "": Close, "D": Delete, "B": ShowInfo, }, queue: { "D": DeleteAll, "": Play, "": Save, "a": AddToPlaylist, "d": Delete, "C": JumpToCurrent, "X": Shuffle, }, ), ) ''; ".config/rmpc/themes/${themeName}.ron".text = let accent = color.hexS.accent; accentHl = color.hexS.accentHl; accentDim = color.hexS.accentDim; accentText = color.hexS.accentText; in '' #![enable(implicit_some)] #![enable(unwrap_newtypes)] #![enable(unwrap_variant_newtypes)] ( default_album_art_path: None, show_song_table_header: true, draw_borders: true, format_tag_separator: " | ", browser_column_widths: [20, 38, 42], modal_backdrop: false, // Don't set backgrounds so it doesn't look super shitty in dark terminals background_color: None, header_background_color: None, modal_background_color: None, text_color: "${color.hexS.text}", preview_label_style: (fg: "${color.hexS.yellow}"), preview_metadata_group_style: (fg: "${color.hexS.yellow}", modifiers: "Bold"), tab_bar: ( enabled: true, active_style: (fg: "${accentText}", bg: "${accent}", modifiers: "Bold|Italic"), inactive_style: (), ), highlighted_item_style: (fg: "${accent}", modifiers: "Bold|Italic"), // Currently playing current_item_style: (fg: "${accentText}", bg: "${accentDim}", modifiers: "Bold|Italic"), // Tracks list cursor borders_style: (fg: "${accent}", modifiers: "Bold"), highlight_border_style: (fg: "${accent}", modifiers: "Bold"), symbols: ( song: "󰝚", dir: "", playlist: "󰲸", marker: "+", ellipsis: "", song_style: None, dir_style: None, playlist_style: None, ), // The stuff shown in the status bar (on the progress bar) level_styles: ( info: (fg: "${accent}", bg: "${accentText}"), warn: (fg: "${color.hexS.yellow}", bg: "${accentText}"), error: (fg: "${color.hexS.red}", bg: "${accentText}"), debug: (fg: "${color.hexS.green}", bg: "${accentText}"), trace: (fg: "${color.hexS.mauve}", bg: "${accentText}"), ), progress_bar: ( // symbols: ["[", "-", ">", " ", "]"], symbols: ["█", "█", "█", "█", "█"], track_style: (fg: "${color.hexS.surface0}"), elapsed_style: (fg: "${accentDim}"), thumb_style: (fg: "${accentDim}"), // "The draggable part" ), scrollbar: ( symbols: ["│", "█", "▲", "▼"], track_style: (fg: "${color.hexS.surface0}"), ends_style: (fg: "${accentDim}"), thumb_style: (fg: "${accentDim}"), // "The draggable part" ), song_table_format: [ ( prop: ( kind: Property(Artist), style: (fg: "${color.hexS.text}"), default: (kind: Text("Unknown")) ), width: "25%", ), ( prop: ( kind: Property(Title), style: (fg: "${color.hexS.text}"), default: (kind: Text("Unknown")) ), width: "40%", ), ( prop: ( kind: Property(Album), style: (fg: "${color.hexS.text}"), default: (kind: Text("Unknown Album"), style: (fg: "white")) ), width: "25%", ), ( prop: ( kind: Property(Duration), style: (fg: "${color.hexS.text}"), default: (kind: Text("-")) ), width: "10%", alignment: Right, ), ], components: {}, layout: Split( direction: Vertical, panes: [ ( pane: Pane(Header), size: "2", ), ( pane: Pane(Tabs), size: "3", ), ( pane: Pane(TabContent), size: "100%", ), ( pane: Pane(ProgressBar), size: "1", ), ], ), header: ( rows: [ // Top Row ( left: [ ( kind: Text("["), style: (fg: "${accentDim}", modifiers: "Bold") ), ( kind: Property(Status(StateV2( playing_label: "Playing", paused_label: "Paused", stopped_label: "Stopped")) ), style: (fg: "${accentDim}", modifiers: "Bold") ), ( kind: Text("]"), style: (fg: "${accentDim}", modifiers: "Bold") ) ], center: [ ( kind: Property(Song(Title)), style: (fg: "${accentDim}", modifiers: "Bold"), default: ( kind: Text("No Song"), style: (fg: "${color.hexS.text}", modifiers: "Bold") ) ) ], right: [ ( kind: Property(Widget(ScanStatus)), style: (fg: "${accentDim}") ), ( kind: Property(Widget(Volume)), style: (fg: "${accentDim}") ) ] ), // Bottom Row ( left: [ ( kind: Property(Status(Elapsed)), style: (fg: "${color.hexS.text}") ), ( kind: Text(" / "), style: (fg: "${color.hexS.text}") ), ( kind: Property(Status(Duration)), style: (fg: "${color.hexS.text}") ), ( kind: Text(" ("), style: (fg: "${color.hexS.text}") ), ( kind: Property(Status(Bitrate)), style: (fg: "${color.hexS.text}") ), ( kind: Text(" kbps)"), style: (fg: "${color.hexS.text}") ) ], center: [ ( kind: Property(Song(Artist)), style: (fg: "${color.hexS.text}", modifiers: "Bold"), default: ( kind: Text("Unknown"), style: (fg: "${color.hexS.text}", modifiers: "Bold") ) ), ( kind: Text(" - "), style: (fg: "${color.hexS.text}") ), ( kind: Property(Song(Album)), style: (fg: "${color.hexS.text}"), default: ( kind: Text("Unknown Album"), style: (fg: "${color.hexS.text}") ) ) ], right: [ ( kind: Property(Status(RepeatV2( on_label: "Repeat (z)", off_label: "Repeat (z)", on_style: (fg: "${accentDim}", modifiers: "Bold|Underlined"), off_style: (fg: "${color.hexS.text}"), ))), ), ( kind: Text(" / "), style: (fg: "${color.hexS.text}"), ), ( kind: Property(Status(RandomV2( on_label: "Random (x)", off_label: "Random (x)", on_style: (fg: "${accentDim}", modifiers: "Bold|Underlined"), off_style: (fg: "${color.hexS.text}"), ))), ), ( kind: Text(" / "), style: (fg: "${color.hexS.text}"), ), ( kind: Property(Status(ConsumeV2( on_label: "Consume (c)", oneshot_label: "Consume OS (c)", off_label: "Consume (c)", on_style: (fg: "${accentDim}", modifiers: "Bold|Underlined"), oneshot_style: (fg: "${accentDim}", modifiers: "Bold|Underlined"), off_style: (fg: "${color.hexS.text}"), ))), ), ( kind: Text(" / "), style: (fg: "${color.hexS.text}"), ), ( kind: Property(Status(SingleV2( on_label: "Single (v)", oneshot_label: "Single OS (v)", off_label: "Single (v)", on_style: (fg: "${accentDim}", modifiers: "Bold|Underlined"), oneshot_style: (fg: "${accentDim}", modifiers: "Bold|Underlined"), off_style: (fg: "${color.hexS.text}") ))), ), ] ), ], ), browser_song_format: [ ( kind: Group([ (kind: Property(Track)), (kind: Text(" ")), ]) ), ( kind: Group([ (kind: Property(Artist)), (kind: Text(" - ")), (kind: Property(Title)), ]), default: (kind: Property(Filename)) ), ], lyrics: ( timestamp: false ), cava: ( // symbols that will be used to draw the bar in the visualiser, in ascending order of // fill fraction bar_symbols: ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'], // similar to bar_symbols but these are used for the top-down rendering, meaning for orientation // "Horizontal" and "Top" inverted_bar_symbols: ['▔', '🮂', '🮃', '▀', '🮄', '🮅', '🮆', '█'], // bg_color: "black", // background color, defaults to rmpc's bg color if not provided bar_width: 1, // width of a single bar in columns bar_spacing: 1, // free space between bars in columns // Possible values are "Top", "Bottom" and "Horizontal". Top makes the bars go from top to // bottom, "Bottom" is from bottom up, and "Horizontal" is split in the middle with bars going // both down and up from there. // Using non-default symbols with "Top" and "Horizontal" may produce undesired output. orientation: Bottom, // Colors can be configured in three different ways: a single color, different colors // per row and a gradient. You can use the same colors as everywhere else. Only specify // one of these: // Every bar symbol will be red // bar_color: Single("red"), // The first two rows(two lowest amplitudes) will be red, after that two green rows // and the rest will be blue. You can have as many as you want here. The last value // will be used if the height exceeds the length of this array. // bar_color: Rows([ // "red", // "red", // "green", // "green", // "blue", // ]), // A simple color gradient. This is a map where keys are percent values of the height // where the color starts. After that it is linearly interpolated towards the next value. // In this example, the color will start at green for the lowest amplitudes, go towards // blue at half amplitudes and finishing as red for the highest values. Keys must be between // 0 and 100 and if the first or last key are not 0 and 100 respectively, the lowest and highest // value will be used as 0 and 100. Only hex and RGB colors are supported here and your terminal // must support them as well! bar_color: Gradient({ 0: "${accentDim}", 100: "${accent}", }), ), ) ''; }; }; }