Giter VIP home page Giter VIP logo

mcthomas / apple-music-cli-player Goto Github PK

View Code? Open in Web Editor NEW
81.0 6.0 8.0 2.74 MB

A simple command-line Apple Music controller script which includes a "Now Playing" widget function, a playback function, and a list-out function for your Mac's Music.app library, written in sh.

License: MIT License

Shell 93.39% AppleScript 6.61%
apple applescript automation cli macos music osascript terminal tui widget

apple-music-cli-player's Introduction

Apple Music CLI Player

Tested on macOS 12 & 13 (likely to work on macOS 10.15, 11). Can be called with the system default zsh. I recommend aliasing am.sh to alias am=zsh path/to/am.sh, or moving its three individual functions into your .zshrc.

Goal: Provide a simple command-line interface to listing out, playing songs from, and utilizing controls for Music.app. I decided against using a library such as ncurses to build a full TUI application, as I think it is preferable to interface via quick commands and a light "widget".

Now Playing (np)

Enjoy a simple "Now Playing" widget from your terminal. Uses standard Unix tooling/piping, AppleScript for interfacing with Apple Music, and Viu for displaying the album art images. It also includes keyboard shortcut bindings for basic playback controls. Apart from toggling shuffle, toggling repeat, and changing the Music.app-specific volume, the other controls are already accessible from the special Fn key functions/touch bar.

Dependencies: Viu (unless you always use text mode)

Configuration:

  • Place album-art.applescript at ~/Library/Scripts/album-art.applescript, or configure a valid path in the np() func of am.sh for wherever you decide to keep it
  • (Optional) In the np() func of am.sh, adjust the -h dimension of the album art (look for the two calls to viu) to ensure a square appearance with your terminal emulator's line spacing

Usage (aliased): am np

Usage (not aliased): zsh am.sh np

np                    Open the "Now Playing" TUI widget.
                      (Music.app track must be actively
		      playing or paused)
np -t		      Open in text mode (disables album art)

np keybindings:

p                     Play / Pause
f                     Forward one track
b                     Backward one track
>                     Begin fast forwarding current track
<                     Begin rewinding current track
R                     Resume normal playback
+                     Increase Music.app volume 5%
-                     Decrease Music.app volume 5%
s                     Toggle shuffle
r                     Toggle song repeat
q                     Quit np
Q                     Quit np and Music.app
?                     Show / hide keybindings

Notes:

  • Attempting to play the previous track with an empty queue will kill the script
  • album-art.applescript is a modified version of this script, written by AppleScript wizard Doug Adams

List

List out all song groupings of a specific type or all songs of a specific song grouping in your library. The song grouping type is dictated by the flag you pass. By calling list without specifying a title after the flag, you will see a printout of all the titles of that flag's collection type.

Usage (aliased): am list [-grouping] [name]

Usage (not aliased): zsh am.sh list [-grouping] [name]

list -s               List all songs in your library.
list -r               List all records.
list -r PATTERN       List all songs in the record PATTERN.
list -a               List all artists.
list -a PATTERN       List all songs by the artist PATTERN.
list -p               List all playlists.
list -p PATTERN       List all songs in the playlist PATTERN.
list -g               List all genres.
list -g PATTERN       List all songs in the genre PATTERN.

Example: am list -r In Rainbows (not case-sensitive)

Notes:

  • Music.app does not need to be open or closed; it should launch itself silently when list is called
  • Only works on tracks saved to your Library (but they do not need to be downloaded)
  • Remember to escape any special characters or punctuation if passing a title (or wrap it in double quotes)

Play

Begin playback of different song groupings or a specific song grouping in your library. The song grouping type is dictated by the flag you pass. By calling play without specifying a title after the flag, you are prompted to select a title of that flag's collection type on the fly via fzf. Unfortunately there is no simple way to play, for example, a specific album or songs from a specific artist with AppleScript, but I was able to modify code shared by a "jccc" here, as a workaround which involves automatically creating a single temporary playlist in your library that is utilized by play().

Dependencies: fzf (unless you always play groupings by name)

Usage (aliased): am play [-grouping] [name]

Usage (not aliased): zsh am.sh play [-grouping] [name]

play -s               Fzf for a song and begin playback.
play -s PATTERN       Play the song PATTERN.
play -r               Fzf for a record and begin playback.
play -r PATTERN       Play from the record PATTERN.
play -a               Fzf for an artist and begin playback.
play -a PATTERN       Play from the artist PATTERN.
play -p               Fzf for a playlist and begin playback.
play -p PATTERN       Play from the playlist PATTERN.
play -g               Fzf for a genre and begin playback.
play -g PATTERN       Play from the genre PATTERN.
play -l               Play from your entire library.

Example: am play -a Radiohead (not case-sensitive)

Notes:

  • Music.app does not need to be open or closed; it should launch itself silently when play is called
  • Only works on tracks saved to your Library (but they do not need to be downloaded)
  • Remember to escape any special characters or punctuation if passing a title (or wrap it in double quotes)
  • calling -p Library will result in quite a delay, unlike -l, because it requires copying all the songs in your library into the temporary playlist

Optional AirPlay Snippet (not in src)

Toggle the Music.app AirPlay audio output for a specific device.

Configuration:

  • Adjust the device strings to a device hostname of your choosing
  • Ideally adapt the argument name to match
if [ $1 = "atv" ]
   then
    isActive=$(osascript -e 'tell application "Music" to get selected of AirPlay device "Apple TV"')
    if [ $isActive = 'false' ]
    then
      osascript -e 'tell application "Music" to set selected of AirPlay device "Apple TV" to true'
    else
      osascript -e 'tell application "Music" to set selected of AirPlay device "Apple TV" to false'
  fi
fi

Example: zsh ap.sh atv

Known Problems

  • Error: execution error: Music got an error: Application isn’t running. (-600)
    • Solution: Reboot. It seems to occur occasionally after having had Music.app open for too long while your Mac has slept. Other potential solutions can be found here
  • Blinking for each output refresh when running np()
    • Consider using a lighter-weight terminal emulator, or even Terminal.app, where this doesn't seem to occur. I am not sure how to mitigate this for heavier terminal emulators such as iTerm2

Ideas For Improvement

  • am.sh could be expanded with a function to call new AppleScript snippets to create, delete, or refine playlists; it would also be nice to be able to queue (as apposed to immediately play) a song or a group of songs, which is possible (though there is no native corresponding AppleScript function to accomplish this at present)
  • This project could be forked and used in the backend to create a full client alternative to Music.app, though it would not be possible to browse for and save tracks outside of the user's library
  • See the Script Editor.app's dictionary API (Music.sdef) for an exhaustive reference of all the native Music.app variables and functions that can be interfaced via AppleScript

apple-music-cli-player's People

Contributors

mcthomas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar

apple-music-cli-player's Issues

Add albums to library from command-line?

This script works well for music already in the user's library. Might you consider expanding it to play content that isn't yet in the library? I think this should be possible with AppleScript. At a minimum, you can open a itms:// item from the shell which will cause that URL to start playing in Music.app, even if it's not currently in the library. These links can be found by web-searching for the album/artist/track name + music.apple.com, and then replacing https:// with itms://

Option to disable album art?

First off, thank you for this! Nice to be able to have a CLI interface without the Music app in your face.

Is there a way to completely disable album art display? I would like to have the np output by itself and not have a big black square on the left side of the output.

pr -T 'illegal option'

Hi, thanks for this seemingly cool script, but my first test resulted in an error:

➜ ~ am list -p pr: illegal option -- T usage: pr [+page] [-col] [-adFfmprt] [-e[ch][gap]] [-h header] [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset] [-L locale] [-s[ch]] [-w width] [-] [file ...]

Tested on macOS 12.6.1, and it appears pr -T is no longer a valid option.

content inset from left edge of terminal

Describe the bug
each line of the player begins at between 27 and 32 spaces from the left edge of the terminal

To Reproduce
running zsh am.sh np (default usage)

Expected behavior
text should be left justified

Desktop (please complete the following information):

  • OS: iOS Monterey

I cannot determine from the code what's causing the indenting. This behavior is probably by design, not a bug, but either way I would appreciate knowing how to adjust the appearance of the player, particularly, the indentation. Thanks very much. Really love this player.

am np results in timeout error

When I start am np I get the following error:
bash: line 0: read: .5: invalid timeout specification

It appears zsh (at least the version i'm running can't handle decimal numbers. If I change the following line
input=$(bash -c "read -n 1 -t .5 input; echo \$input | xargs")
to
input=$(bash -c "read -n 1 -t 1 input; echo \$input | xargs")
the error disappears.

macOS 12.6.1 and zsh 5.8.1 (x86_64-apple-darwin21.0)

Search for artist, album, song, playlist by pattern?

Would you consider adding the ability to search for content by pattern? This would just require adding a command-line option that would accept a pattern and then grepping that pattern from the osascript output.

For example,

am list -a -r '.*Monk.*'

would search for every artist with the string "Monk" in it, which would capture "Thelonious Monk," as well as "The Thelonious Monk Quartet," etc.

Maybe easier to just have it be a substring rather than regexp match so -r 'monk' would return everything that has "monk" anywhere in it.

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.