xenodium / ready-player

GNU General Public License v3.0
136 stars 7 forks source link

Feature request: handle m3u playlists #14

Closed ericsfraga closed 1 month ago

ericsfraga commented 2 months ago

It would be great if ready player would handle m3u files which consist simply of a list of media files, aka play lists.

Thanks.

ericsfraga commented 2 months ago

Ah, I just saw your post on dired etc. which includes code to mimic a playlist mode. That'll do!

xenodium commented 2 months ago

lol I was just about to mention the post ;)

I haven't got many playlists, so I'd love to hear how well the snippets in the post works for you before considering package inclusion.

Btw, I just made a tweak to the snippet. I'll post here too.

(defun ready-player-load-m3u-playlist ()
  "Load an .m3u playlist."
  (interactive)
  (let* ((m3u-path (read-file-name "find m3u: " nil nil t nil
                                   (lambda (name)
                                     (or (string-match "\\.m3u\\'" name)
                                         (file-directory-p name)))))
         (media-files (if (string-match "\\.m3u\\'" m3u-path)
                          (ready-player--media-at-m3u-file m3u-path)
                        (error "Not a .m3u file")))
         ;; Find a common parent via completion.
         ;; Is there a better alternative?
         (default-directory (file-name-directory
                             (try-completion "" media-files)))
         (m3u-fname (file-name-nondirectory m3u-path))
         (dired-buffer-name (format "*%s*" m3u-fname))
         (dired-buffer (dired (append (list dired-buffer-name)
                                      (mapcar (lambda (path)
                                                (file-relative-name path default-directory))
                                              media-files)))))
    (ready-player-load-dired-playback-buffer dired-buffer)))

(defun ready-player--media-at-m3u-file (m3u-path)
  "Read m3u playlist at M3U-PATH and return files."
  (with-temp-buffer
    (insert-file-contents m3u-path)
    (let ((files))
      (while (re-search-forward
              (rx bol (not (any "#" space))
                  (zero-or-more (not (any "\n")))
                  eol) nil t)
        (when (file-exists-p (match-string 0))
          (push (match-string 0) files)))
      (nreverse files))))
ericsfraga commented 2 months ago

I'm using it right now (the version in the blog post) and it starting well although I had to edit my playlist file to have full paths for the file names.

The player did quit playing at one song and I had to manually go into the dired buffer that had been created and select the next file. However, then the "next" item played was from the actual directory that file was in, not the next in the dired buffer created by your play list function.

I'll start my play list again with the updated codes and will report back.

xenodium commented 2 months ago

Does that mean the paths are relative to the location of the list file?

I don't have real world files other than the ones I experimented with. Would love to see more. Mind sharing your playlist file?

Would be good to know if there was anything of interest about the file parh that stopped playing?

If the file is reopened from the m3u dired directory, it should have maintained m3u playback. If opened from a different dired buffer, the list is forgotten. If not, that's a bug. Maybe I can add additional logic to make things a little smarter.

ericsfraga commented 2 months ago

My playlist file, initially, consisted of file paths relative to where the .m3u file was, e.g.

Rihanna/Good_Girl_Gone_Bad/13_Cry.ogg
The_Cardigans_-_Lovefool.ogg

choosing two lines at random from a large playlist.

The file which fails fails when visited directly as well and, interestingly, mpv fails when trying to play that file as well. ogg123 plays it fine, however. Strange. Ready-player simply stops playing it (or trying to play it, I guess) but doesn't move on to the next.

Update. Audacious plays the track as well.

xenodium commented 2 months ago

mpv fails when trying to play that file as well. ogg123 plays it fine, however.

ready-player is delegating to utils like mpv. I recently added logic to enable different utilities for video vs audio. https://www.emacs.dyerdwelling.family/emacs/20240811115938-emacs--ready-player-mode-different-utilities-for-video-and-audio

We should be able to use the same mechanism to target more appropriate tools per file. I'll extend it...

Ready-player simply stops playing it (or trying to play it, I guess) but doesn't move on to the next.

This needs a bit of logic at the moment since non-zero exit code stops playback altogether. Having said that, if you do run into this issue again, press "n" or the ">>" button, and it should go to the next file without issues.

Update. Audacious plays the track as well.

Good to know. I'll start with a helper for ogg123. In your case, if audacious plays all your audio files without issues, you can use something like this:

(use-package ready-player
  :custom
  (ready-player-open-playback-commands
    '((ready-player-is-audio-p "audacious")
      (ready-player-is-video-p "mpv")))
  :config
  (ready-player-mode +1))
ericsfraga commented 2 months ago

Thanks for all of this. I've incorporated your suggested configuration code into my init files.

xenodium commented 2 months ago

I've incorporated your suggested configuration code into my init files.

Lemme know how you get on with m3u lists after some usage. Maybe we can consider including in package.

(ready-player-is-audio-p "audacious")

As of https://github.com/xenodium/ready-player/commit/df6107a670eb301a5f49a7e16c5fccc17f8bf84d we can now use extensions to determine utility:

(setq ready-player-open-playback-commands
      '((("mp3" "ogg") "audacious")
        ("mpv" "--audio-display=no")
        ("vlc")
        ("ffplay")
        ("mplayer")))
xenodium commented 1 month ago

Maybe we can consider including in package.

Heads-up ready-player-load-m3u-playlist is now included in the package.

xenodium commented 1 month ago

Version 0.14.1 has improvements remembering the playlist (in case another file is open from a different dired buffer), but the more significant new feature is metadata indexing of the current playlist. Use / bindings to fuzzy search using metadata.

2024-09-04--Emacs_optimized

xenodium commented 1 month ago

Version 0.18.1 now recognizes m3u files. No need to invoke M-x ready-player-load-m3u-playlist. Can just open .m3u as any other file.

xenodium commented 1 month ago

Feature's in place now. Gonna go ahead and close this feature request.

Please consider supporting the project to make feature requests, improvements, and maintenance sustainable.