Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions lua/music_player.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
---@param exe string
---@return string[] cmd
local function generate_find_cmd(exe)
local cmd = ("%s --type f"):format(exe)
for _, ext in ipairs({ "mp3", "flac", "m4a" }) do
cmd = ("%s --extension %s"):format(cmd, ext)
end

return vim.split(cmd, " ", { plain = true, trimempty = true })
end

---@class MusicPlayer
local M = {}

function M.browse()
local fd_exe = ""
if vim.fn.executable("fd") == 1 then
fd_exe = "fd"
elseif vim.fn.executable("fdfind") == 1 then
fd_exe = "fdfind"
else
if vim.fn.executable("fd") ~= 1 and vim.fn.executable("fdfind") ~= 1 then
vim.notify("`fd` is not installed!", vim.log.levels.ERROR)
return
end
Expand All @@ -22,16 +28,25 @@ function M.browse()
end
end

fd_exe = vim.fn.executable("fdfind") == 1 and "fdfind" or "fd"

local target = vim.fn.expand("~/Music")
if vim.fn.isdirectory(target) ~= 1 then
error(("Directory not found: `%s`"):format(target), vim.log.levels.ERROR)
end

require("telescope.builtin").find_files({
prompt_title = "🎵 Music Library",
cwd = vim.fn.expand("~/Music"),
find_command = { fd_exe, "--type", "f", "--extension", "mp3", "--extension", "flac" },
attach_mappings = function(promp_bufnr, map)
cwd = target,
find_command = generate_find_cmd(fd_exe),
---@param prompt_bufnr integer
---@param map fun(mode: string, lhs: string, rhs: string|function)
attach_mappings = function(prompt_bufnr, map)
map("i", "<CR>", function()
local selection = require("telescope.actions.state").get_selected_entry()
require("telescope.actions").close(promp_bufnr)
require("telescope.actions").close(prompt_bufnr)
if selection and selection.path then
vim.cmd.MusicPlay(vim.fn.fnameescape(selection.path))
vim.cmd.MusicPlay(vim.fn.fnamemodify(selection.path, ":p"))
end
end)

Expand Down
59 changes: 43 additions & 16 deletions rplugin/python3/music_player.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Python code for ``nvim-music-player``."""
from os.path import exists, expanduser
from os.path import exists, realpath
from shutil import which
from subprocess import DEVNULL, Popen
from typing import NoReturn, Tuple
Expand All @@ -16,43 +16,70 @@ class MusicPlayer:
----------
nvim : pynvim.Nvim
The Neovim instance.

Attributes
----------
nvim : pynvim.Nvim
The Neovim instance.
file : str or None
The currently playing file path.
process : subprocess.Popen or None
The ``mpv`` process.
"""

nvim: pynvim.Nvim
process: Popen | None
file: str | None
cmd: str | None

def __init__(self, nvim: pynvim.Nvim):
self.cmd: str | None = which("mpv")
self.nvim: pynvim.Nvim = nvim
self.process: Popen | None = None
self.nvim.out_write("🎵 nvim-music-player loaded\n")
self.file: str | None = None

@pynvim.command("MusicPlay", nargs=1, complete="file")
def play(self, args: Tuple[str]) -> NoReturn:
"""Start playing the given music file."""
if not which("mpv"):
self.nvim.err_write("Unable to find mpv in PATH\n")
if self.cmd is None:
self.nvim.err_write("🎵 nvim-music-player: Unable to find `mpv` in PATH\n")
return

path = expanduser(args[0].replace('\\ ', ' '))
path: str = realpath(args[0].replace('\\ ', ' '))
if not exists(path):
self.nvim.err_write(f"❌ File not found: {path}\n")
self.nvim.err_write(f"🎵 nvim-music-player: ❌ File not found: {path}\n")
return

if self.file is not None and self.file == path:
self.stop()
return

self.file = path
if self.process is not None:
self.process.terminate()

self.process = Popen(["mpv", "--no-video", path], stdout=DEVNULL, stderr=DEVNULL)
self.nvim.out_write(f"🎶 Playing: {path}\n")
self.process = Popen([self.cmd, "--no-video", path], stdout=DEVNULL, stderr=DEVNULL)
self.nvim.out_write(f"🎵 nvim-music-player: 🎶 Playing: {path}\n")

@pynvim.command("MusicStop", nargs=0, bang=True)
def stop(self, bang: bool = False) -> NoReturn:
"""
Stop the music player.

Parameters
----------
bang : bool, optional, default=False
Whether the command was called with a bang (``!``) or not.
"""
if self.process is None:
if not bang:
self.nvim.out_write("🎵 nvim-music-player: Music already stopped\n")

@pynvim.command("MusicStop", nargs=0)
def stop(self) -> NoReturn:
"""Stop the music player."""
if self.process is not None:
self.process.terminate()
self.process = None
self.nvim.out_write("⏹ Music stopped\n")
return

self.nvim.out_write("Music already stopped\n")
self.process.terminate()
self.process = None
self.file = None
self.nvim.out_write("🎵 nvim-music-player: ⏹ Music stopped\n")

# vim: set ts=4 sts=4 sw=4 et ai si sta: