├── LICENSE ├── README.md ├── Spotify.Commands.alfredworkflow ├── applescript ├── SpotifyVolumeUp.applescript ├── copyTrackURL.applescript ├── displayTrackInfo.applescript ├── nextTrack.applescript ├── playPlaylist.applescript ├── previousTrack.applescript ├── quitSpotify.applescript ├── spotifyPause.applescript ├── spotifyVolumeDown.applescript ├── toggleLoop.applescript └── toggleShuffle.applescript └── python └── systemPause.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 SoloUnity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

5 | Spotify Commands 6 |

7 | 8 | Locally run Spotify media controls through global keyboard commands or keywords. Avoid the need to rely on external servers! Plus discord bot inspired keywords in case you forget your commands. 9 | 10 |
11 | 12 |
13 | 14 | # What are the requirements? 15 | - MacOS 16 | - [Alfred](https://www.alfredapp.com) 17 | - Alfred PowerPack 💰(Paid) 18 | 19 | # How do I install it? 20 | 1) Check [releases](https://github.com/SoloUnity/alfred-Spotify-Commands/releases) 21 | 2) Download the latest version of the workflow 22 | 3) Double click the downloaded workflow file and import it into alfred 23 | 4) Customize by setting up your own commands 24 | 25 | # How does this work? 26 | The workflow uses both python and Spotify's applescriptAPI to interface with Spotify and macOS, bypassing the need to use the Spotify API and talk to Spotify servers. This means that it works offline and without delay! 27 | 28 | # Keywords 29 | 30 | | Spotify Actions | Keywords | 31 | | ------------- | ------------- | 32 | | Play/Pause | !p | 33 | | Next Song | !s | 34 | | Previous Song | !b | 35 | | Volume Up | !sup | 36 | | Volume Down | !sdown | 37 | | Toggle Shuffle | !shuffle | 38 | | Toggle Loop | !loop | 39 | | Quickplay Playlist | !q | 40 | | Song Information | !song | 41 | | Copy Song URL | !copy | 42 | 43 | | System Actions | Keywords | 44 | | ------------- | ------------- | 45 | | Play/Pause | !p | 46 | | Volume Up | !volup | 47 | | Volume Down | !voldown | 48 | | Quit Spotify | !quit | 49 | | Toggle Spotify Focus| !show | 50 | 51 | # Acknowledgements 52 | Workflow Icon: [@FelixMeens](https://twitter.com/FelixMeens) 53 | 54 | Displaying Current Track Information (v0.0.7 and older): [WhoDis Workflow](https://github.com/blackspike/spotify-whodis-alfred-workflow) 55 | 56 | Emulated Pause Key: [@fredrikw](https://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac) 57 | 58 | 59 | -------------------------------------------------------------------------------- /Spotify.Commands.alfredworkflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoloUnity/alfred-spotify-commands/62f1ead3159ef289aff6b4a2f750cc3336dc1fad/Spotify.Commands.alfredworkflow -------------------------------------------------------------------------------- /applescript/SpotifyVolumeUp.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | set sound volume to sound volume + 11 4 | end tell 5 | end alfred_script -------------------------------------------------------------------------------- /applescript/copyTrackURL.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | get spotify url of current track 4 | end tell 5 | end alfred_script -------------------------------------------------------------------------------- /applescript/displayTrackInfo.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | 4 | set currentTrack to the current track 5 | set currentName to the name of currentTrack as string 6 | set currentArtist to the artist of currentTrack as string 7 | set currentAlbum to the album of currentTrack as string 8 | 9 | display notification "by " & currentArtist & " from the album " & currentAlbum with title currentName 10 | 11 | end tell 12 | 13 | end alfred_script -------------------------------------------------------------------------------- /applescript/nextTrack.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | next track 4 | end tell 5 | end alfred_script -------------------------------------------------------------------------------- /applescript/playPlaylist.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | -- Paste IN BETWEEN quotations on the line below 4 | play track "spotify:playlist:66AeDiMrDqXStAK0DnrcYA" 5 | end tell 6 | end alfred_script -------------------------------------------------------------------------------- /applescript/previousTrack.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | previous track 4 | end tell 5 | end alfred_script -------------------------------------------------------------------------------- /applescript/quitSpotify.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" to quit 3 | end alfred_script -------------------------------------------------------------------------------- /applescript/spotifyPause.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | playpause 4 | end tell 5 | end alfred_script 6 | -------------------------------------------------------------------------------- /applescript/spotifyVolumeDown.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | set sound volume to sound volume - 11 4 | end tell 5 | end alfred_script -------------------------------------------------------------------------------- /applescript/toggleLoop.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | set repeating to not repeating 4 | if repeating then 5 | set isRepeating to "off" 6 | else 7 | set isRepeating to "on" 8 | end if 9 | end tell 10 | end alfred_script -------------------------------------------------------------------------------- /applescript/toggleShuffle.applescript: -------------------------------------------------------------------------------- 1 | on alfred_script(q) 2 | tell application "Spotify" 3 | set shuffling to not shuffling 4 | if shuffling then 5 | set isShuffling to "off" 6 | else 7 | set isShuffling to "on" 8 | end if 9 | end tell 10 | end alfred_script -------------------------------------------------------------------------------- /python/systemPause.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # CLI program to control the mediakeys on OS X. Used to emulate the mediakey on a keyboard with no such keys. 4 | # Easiest used in combination with a launcher/trigger software such as Quicksilver. 5 | # Main part taken from http://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac 6 | # Glue to make it into cli program by Fredrik Wallner http://www.wallner.nu/fredrik/ 7 | 8 | import Quartz 9 | import sys 10 | 11 | # NSEvent.h 12 | NSSystemDefined = 14 13 | 14 | # hidsystem/ev_keymap.h 15 | NX_KEYTYPE_SOUND_UP = 0 16 | NX_KEYTYPE_SOUND_DOWN = 1 17 | NX_KEYTYPE_PLAY = 16 18 | NX_KEYTYPE_NEXT = 17 19 | NX_KEYTYPE_PREVIOUS = 18 20 | NX_KEYTYPE_FAST = 19 21 | NX_KEYTYPE_REWIND = 20 22 | 23 | supportedcmds = {'playpause': NX_KEYTYPE_PLAY, 'next': NX_KEYTYPE_NEXT, 'prev': NX_KEYTYPE_PREVIOUS, 'volup': NX_KEYTYPE_SOUND_UP, 'voldown': NX_KEYTYPE_SOUND_DOWN} 24 | 25 | def HIDPostAuxKey(key): 26 | def doKey(down): 27 | ev = Quartz.NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_( 28 | NSSystemDefined, # type 29 | (0,0), # location 30 | 0xa00 if down else 0xb00, # flags 31 | 0, # timestamp 32 | 0, # window 33 | 0, # ctx 34 | 8, # subtype 35 | (key << 16) | ((0xa if down else 0xb) << 8), # data1 36 | -1 # data2 37 | ) 38 | cev = ev.CGEvent() 39 | Quartz.CGEventPost(0, cev) 40 | doKey(True) 41 | doKey(False) 42 | 43 | if __name__ == "__main__": 44 | try: 45 | command = sys.argv[1] 46 | assert(command in supportedcmds) 47 | HIDPostAuxKey(supportedcmds[command]) 48 | except (IndexError, AssertionError): 49 | print "Usage: %s command" % (sys.argv[0],) 50 | print "\tSupported commands are %s" % supportedcmds.keys() --------------------------------------------------------------------------------