GithubHelp home page GithubHelp logo

rofi_mpd's Introduction

Rofi MPD

This is a simple MPD client for quickly adding albums or tracks using Rofi. It supports a variety of modes, and can group longer albums by disc number (or even disc name).

Demo Gif

Installation

Unsurprisingly, you will require both MPD and Rofi to be installed. You will also require Python >= 3.6.

Python Package

You can install the pypi package using pip3 install Rofi-MPD.

Make sure wherever it is installed to is on your path. You can check with pip3 show Rofi-MPD.

Arch Linux

Arch users can install the rofi-mpd-git package.

NixOS

NixOS users can add rofi-mpd to their environment.systemPackages or run nix-env -iA nixos.rofi-mpd. The derivation can be found here

Other

Clone this repo somewhere, then run:

pip3 install -r requirements.txt

You may wish to use the provided script, in which case it needs to be marked as executable:

chmod +x bin/rofi-mpd

Usage

If installed using a package manager, a script should have automatically been put on your path:

rofi-mpd # Normal usage
rofi-mpd -h # See help

If not, you can either do:

python3 rofi_mpd/rofi_mpd.py
# or
bin/rofi-mpd

By default, a list of artists is shown.

The program will take a second or so to load data from MPD. This data is cached for 10 minutes in the database file.

Short Long Description Default
-h --help Shows CLI help and exits -
-w --artists Shows a list of all artists True
-b --albums Shows a list of all albums False
-t --tracks Shows a list of all tracks False
-g --genres Shows a list of genres False
-a --playlists Shows a list of playlists False
-m --music-directory Specifies the path to your music library ~/Music
-c --host Specifies the MPD server host localhost
-p --port Specifies the MPD server port 6600
--play Start playback on track add None (uses config value)
--noplay Do not start playback on track add None (uses config value)
-i --case-sensitive Enables case sensitivity False
-r --args Space-separated command line arguments to be passed to Rofi []

Configuration

Settings are stored in ~/.config/rofi-mpd/config.toml. Many of these can be overridden using the arguments above so act as defaults.

Below is an example config file with each option explained:

music_directory = "~/Music" # Same as MPD `music_directory`
case_sensitive = false # Should searching be case sensitive by default?

# Should disc name tags be read?
# This requires opening the file to read its tags.
# Disc names can be stored in the `TSST` tag.
enable_disc_names = true

tracks_keep_open = false # Should the track selection menu re-open on selection?
discs_keep_open = true # Should the disc selection menu re-open on selection?

play_on_add = false # Should playback start as soon as tracks are added?

# Multiple hosts can be defined.
# If more than one host is defined, a menu is initially opened
# from which a host is selected.
# Passing the host argument bypasses this.
[[hosts]]
host = "localhost"
port = 6600

[[hosts]]
host = "media-server"
port = 6600

rofi_mpd's People

Contributors

jakestanger avatar monsieurh avatar oro avatar rubdos avatar singiamtel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rofi_mpd's Issues

More options for playing songs?

Hiya!

This plugin seems to work after adding some mediainfo to files.

Is it possible to add different options for better controls?

Like playing the song straight after choosing it?

AUR package missing dependencies

Since restructuring the package the AUR package will no longer install. I do not use Arch any more so I'm unable to test this. If anybody can update it that'd be great; it should only be changing a couple of paths.

Crash after selecting album

And I'm back! :-)

Traceback (most recent call last):
  File "/usr/bin/rofi-mpd", line 303, in <module>
    select_album(selection_list, full_album=True)
  File "/usr/bin/rofi-mpd", line 258, in select_album
    select(artist or 'All Albums', data, full_album=full_album)
  File "/usr/bin/rofi-mpd", line 226, in select
    select_track(selection_list, selected_data['artist'], selected_data['album'])
  File "/usr/bin/rofi-mpd", line 267, in select_track
    key=lambda x: (int(x['data']['disc'] if 'disc' in x['data'] else 1),
  File "/usr/bin/rofi-mpd", line 267, in <lambda>
    key=lambda x: (int(x['data']['disc'] if 'disc' in x['data'] else 1),
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

Apparently this disc can be a list, but I have no clue what it means. Same with track number, apparently:

[{'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/01 Lament.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '293', 'duration': '293.486', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': 'a4229593-32d1-4c6d-a97c-88486712f761', 'title': 'Lament', 'track': ['1', '1']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/02 Nascent.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '249', 'duration': '249.313', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': 'd9966081-a00d-4103-8fec-e8ce0831ccd5', 'title': 'Nascent', 'track': ['2', '2']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/03 Concealing Fate, Part 1_ Acceptance.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '514', 'duration': '513.566', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': '885db8e6-aedd-43cf-8af3-6aee3e39e300', 'title': 'Concealing Fate, Part 1: Acceptance', 'track': ['3', '3']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/04 Concealing Fate, Part 2_ Deception.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '323', 'duration': '322.873', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': '042ce449-79ee-4106-a03e-9ea5256a4391', 'title': 'Concealing Fate, Part 2: Deception', 'track': ['4', '4']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/05 Concealing Fate, Part 3_ The Impossible.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '291', 'duration': '290.806', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': 'a598391c-bd49-48bf-b7e4-fe28fb26720f', 'title': 'Concealing Fate, Part 3: The Impossible', 'track': ['5', '5']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/06 Concealing Fate, Part 4_ Perfection.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '158', 'duration': '158.286', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': 'a031b366-7500-4ea5-be98-a6f6a49de6ff', 'title': 'Concealing Fate, Part 4: Perfection', 'track': ['6', '6']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/07 Concealing Fate, Part 5_ Epiphany.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '89', 'duration': '89.246', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': '9fd1f32c-7819-4a0f-90ee-1330445c7fcf', 'title': 'Concealing Fate, Part 5: Epiphany', 'track': ['7', '7']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/08 Concealing Fate, Part 6_ Origin.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '284', 'duration': '284.446', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': '4eb3f3d3-dad4-4b4d-8893-1d7a79577627', 'title': 'Concealing Fate, Part 6: Origin', 'track': ['8', '8']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/09 Sunrise.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '237', 'duration': '237.353', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': '5df4b626-18ea-4dff-8959-a3fed358fb2a', 'title': 'Sunrise', 'track': ['9', '9']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/10 April.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '289', 'duration': '288.939', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': '22a976f1-77f1-45a5-8d2b-2f6238dbb417', 'title': 'April', 'track': ['10', '10']}}, {'type': <ItemType.track: 'track'>, 'data': {'file': 'TesseracT/One/11 Eden.opus', 'last-modified': '2018-07-22T19:49:07Z', 'time': '548', 'duration': '548.206', 'album': 'One', 'albumartist': 'TesseracT', 'albumartistsort': 'TesseracT', 'artist': 'TesseracT', 'artistsort': 'TesseracT', 'date': '2011-03-22', 'disc': ['1', '1'], 'genre': 'Progressive Metal', 'musicbrainz_albumartistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_albumid': 'a33554ec-30ac-45e2-835d-c93ed349c718', 'musicbrainz_artistid': 'f1ec4765-e5da-4591-8b50-a8ff9627dda8', 'musicbrainz_trackid': 'ce64b533-8f2f-41c9-b2d3-990e273cf3a4', 'title': 'Eden', 'track': ['11', '11']}}]

This is a dump of list(data) just before the crash site mentioned above.

Both track and disc apparently give a list of twice their number...: 'disc': ['1', '1'], 'track': ['11', '11']

Bug: albums without month-day in their epoch

Traceback (most recent call last):
  File "/usr/bin/rofi-mpd", line 120, in <module>
    'epoch': get_album_release_epoch(song_data=song),
  File "/usr/bin/rofi-mpd", line 86, in get_album_release_epoch
    year, month, day = date.split(split_char)
ValueError: not enough values to unpack (expected 3, got 2)

Apparently I have albums with only year and month in their date... :-)

Date can be a list

Traceback (most recent call last):
  File "main.py", line 123, in <module>
    'epoch': get_album_release_epoch(song_data=song),
  File "main.py", line 77, in get_album_release_epoch
    if date.isnumeric():
AttributeError: 'list' object has no attribute 'isnumeric'

Invalid song dates make Rofi_MPD crash

When I try to run the program I have the following error:


Traceback (most recent call last):
  File "main.py", line 119, in <module>
    'epoch': get_album_release_epoch(song_data=song),
  File "main.py", line 86, in get_album_release_epoch
    epoch = datetime.datetime(int(year), int(month), int(day))
ValueError: month must be in 1..12

I assume some of my songs have invalid dates

License

I'm making a PKGBUILD out of this. Would you mind stating under which license you want to distribute this script? Otherwise I wont be allowed to PKGBUILD it :-)

Doesnt find anything?

Hi I installed this from aur package.

By selecting rofi-mpd it opens up a menu with
Select artist:

and its empty.. pressing enter etc doesnt show me informations about anything.

All the music files are in ~/Music
and mpd should work on 6600 not sure how to debug this.

KeyError when album is not specified

Traceback (most recent call last):
  File "main.py", line 270, in <module>
    select_artist(selection_list)
  File "main.py", line 217, in select_artist
    select(title or 'All Artists', [*data])
  File "main.py", line 188, in select
    select_album(selection_list, selected_data)
  File "main.py", line 223, in select_album
    select(artist or 'All Albums', data, full_album=full_album)
  File "main.py", line 191, in select
    select_track(selection_list, selected_data['artist'], selected_data['album'])
  File "main.py", line 231, in select_track
    data = sorted([*data],
  File "main.py", line 229, in <lambda>
    and (x['data']['album'] == album if album else True), data)
KeyError: 'album'

'dict' object has no attribute 'replace'

Running rofi-mpd -w or with -g crashes with the following error:

~
❯ rofi-mpd -w
Traceback (most recent call last):
  File "/usr/bin/rofi-mpd", line 3, in <module>
    rofi_mpd.run()
  File "/usr/lib/python3.12/site-packages/rofi_mpd/rofi_mpd.py", line 244, in run
    tracks = get_tracks(client, rofi)
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/rofi_mpd/rofi_mpd.py", line 200, in get_tracks
    artist = select_artist(artists, rofi)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/rofi_mpd/rofi_mpd.py", line 54, in select_artist
    index = select(artists, 'Select artist', rofi)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/rofi_mpd/rofi_mpd.py", line 40, in select
    index, key = rofi.select(prompt, data, select=select)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/rofi/rofi.py", line 390, in select
    optionstr = '\n'.join(option.replace('\n', ' ') for option in options)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/rofi/rofi.py", line 390, in <genexpr>
    optionstr = '\n'.join(option.replace('\n', ' ') for option in options)
                          ^^^^^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'replace'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.