├── 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()
--------------------------------------------------------------------------------