Add Hermes music player. (A Pandora client.)

Closes #83.
This commit is contained in:
Kyle Neideck 2016-11-12 20:54:04 +11:00
parent da74e5ea1d
commit b0bfebedc4
6 changed files with 237 additions and 7 deletions

View file

@ -85,6 +85,7 @@
278D71E91CABB6FF00899CF9 /* BGMXPCHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 279597401C996E2000A002FB /* BGMXPCHelperTests.m */; };
278D71F61CABBC3B00899CF9 /* BGMXPCHelperTests-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 278D71F51CABBC3B00899CF9 /* BGMXPCHelperTests-Info.plist */; };
2795973B1C982E4E00A002FB /* BGMXPCListener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2795973A1C982E4E00A002FB /* BGMXPCListener.mm */; };
279F48771DD6D73A00768A85 /* BGMHermes.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F48761DD6D73900768A85 /* BGMHermes.m */; };
27C457E61CF2BC2600A6C9A6 /* BGMAutoPauseMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 27C457E51CF2BC2600A6C9A6 /* BGMAutoPauseMenuItem.m */; };
27D643BE1C9FB84C00737F6E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 27D643BB1C9FB84C00737F6E /* Info.plist */; };
27D643C01C9FB99200737F6E /* BGMXPCHelperService.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D643BA1C9FB84C00737F6E /* BGMXPCHelperService.m */; };
@ -213,6 +214,9 @@
2795973A1C982E4E00A002FB /* BGMXPCListener.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BGMXPCListener.mm; sourceTree = "<group>"; };
2795973C1C982E8C00A002FB /* BGMXPCListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGMXPCListener.h; sourceTree = "<group>"; };
279597401C996E2000A002FB /* BGMXPCHelperTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BGMXPCHelperTests.m; sourceTree = "<group>"; };
279F48751DD6D73900768A85 /* BGMHermes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGMHermes.h; path = "Music Players/BGMHermes.h"; sourceTree = "<group>"; };
279F48761DD6D73900768A85 /* BGMHermes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BGMHermes.m; path = "Music Players/BGMHermes.m"; sourceTree = "<group>"; };
279F48781DD6D94000768A85 /* Hermes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hermes.h; path = "Music Players/Hermes.h"; sourceTree = "<group>"; };
27C457E41CF2BC2600A6C9A6 /* BGMAutoPauseMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGMAutoPauseMenuItem.h; sourceTree = "<group>"; };
27C457E51CF2BC2600A6C9A6 /* BGMAutoPauseMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BGMAutoPauseMenuItem.m; sourceTree = "<group>"; };
27D643B41C9FABBD00737F6E /* BGM_Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGM_Types.h; path = ../SharedSource/BGM_Types.h; sourceTree = "<group>"; };
@ -352,6 +356,8 @@
1C4699461BD5C0E400F78043 /* BGMiTunes.m */,
1C2336DD1BEAE10C004C1C4E /* BGMSpotify.h */,
1C2336DE1BEAE10C004C1C4E /* BGMSpotify.m */,
279F48751DD6D73900768A85 /* BGMHermes.h */,
279F48761DD6D73900768A85 /* BGMHermes.m */,
27379B881C7C562D0084A24C /* BGMVLC.h */,
27379B891C7C562D0084A24C /* BGMVLC.m */,
273F10DD1CC3D0B900C1C6DA /* BGMVOX.h */,
@ -463,6 +469,7 @@
27F7D4911D2484A300821C4B /* Decibel.h */,
27379B851C7C54870084A24C /* iTunes.h */,
27379B861C7C54870084A24C /* Spotify.h */,
279F48781DD6D94000768A85 /* Hermes.h */,
27379B871C7C552A0084A24C /* VLC.h */,
273F10DC1CC3CF9C00C1C6DA /* VOX.h */,
);
@ -733,6 +740,7 @@
1C1962E41BC94E15008A4DF7 /* CARingBuffer.cpp in Sources */,
273F10DF1CC3D0B900C1C6DA /* BGMVOX.m in Sources */,
1CC1DF811BE5068A00FB8FE4 /* CACFArray.cpp in Sources */,
279F48771DD6D73A00768A85 /* BGMHermes.m in Sources */,
1C0BD0A81BF1B029004F4CF5 /* BGMPreferencesMenu.mm in Sources */,
1C1962F41BCABFC5008A4DF7 /* CAHALAudioObject.cpp in Sources */,
27F7D4901D2483B100821C4B /* BGMDecibel.m in Sources */,
@ -1342,6 +1350,7 @@
2743CA001D86CFFA0089613B /* DebugOpt */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
278D71ED1CABB6FF00899CF9 /* Build configuration list for PBXNativeTarget "BGMXPCHelperTests" */ = {
isa = XCConfigurationList;

View file

@ -0,0 +1,30 @@
// This file is part of Background Music.
//
// Background Music is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 2 of the
// License, or (at your option) any later version.
//
// Background Music is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Background Music. If not, see <http://www.gnu.org/licenses/>.
//
// BGMHermes.h
// BGMApp
//
// Copyright © 2016 Kyle Neideck
//
// Superclass/Protocol Import
#import "BGMMusicPlayer.h"
@interface BGMHermes : BGMMusicPlayerBase<BGMMusicPlayer>
@end

View file

@ -0,0 +1,102 @@
// This file is part of Background Music.
//
// Background Music is free software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 2 of the
// License, or (at your option) any later version.
//
// Background Music is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Background Music. If not, see <http://www.gnu.org/licenses/>.
//
// BGMHermes.m
// BGMApp
//
// Copyright © 2016 Kyle Neideck
//
// Self Include
#import "BGMHermes.h"
// Auto-generated Scripting Bridge header
#import "Hermes.h"
// Local Includes
#import "BGMScriptingBridge.h"
// PublicUtility Includes
#undef CoreAudio_ThreadStampMessages
#define CoreAudio_ThreadStampMessages 0 // Requires C++
#include "CADebugMacros.h"
#pragma clang assume_nonnull begin
@implementation BGMHermes {
BGMScriptingBridge* scriptingBridge;
}
- (id) init {
// If you're copying this class, replace the ID string with a new one generated by uuidgen. (Command line tool.)
if ((self = [super initWithMusicPlayerID:[BGMMusicPlayerBase makeID:@"0CDC67B0-56D3-4D94-BC06-6E380D8F5E34"]
name:@"Hermes"
bundleID:@"com.alexcrichton.Hermes"])) {
scriptingBridge = [[BGMScriptingBridge alloc] initWithBundleID:(NSString*)self.bundleID];
}
return self;
}
- (HermesApplication* __nullable) hermes {
return (HermesApplication* __nullable)scriptingBridge.application;
}
- (BOOL) isRunning {
// Note that this will return NO if is self.hermes is nil (i.e. Hermes isn't running).
return self.hermes.running;
}
// isPlaying and isPaused check self.running first just in case Hermes is closed but self.hermes hasn't become
// nil yet. In that case, reading self.hermes.playerState could make Scripting Bridge open Hermes.
- (BOOL) isPlaying {
return self.running && (self.hermes.playbackState == HermesPlayerStatesPlaying);
}
- (BOOL) isPaused {
return self.running && (self.hermes.playbackState == HermesPlayerStatesPaused);
}
- (BOOL) pause {
// isPlaying checks isRunning, so we don't need to check it here and waste an Apple event
BOOL wasPlaying = self.playing;
if (wasPlaying) {
DebugMsg("BGMHermes::pause: Pausing Hermes");
[self.hermes pause];
}
return wasPlaying;
}
- (BOOL) unpause {
// isPaused checks isRunning, so we don't need to check it here and waste an Apple event
BOOL wasPaused = self.paused;
if (wasPaused) {
DebugMsg("BGMHermes::unpause: Unpausing Hermes");
[self.hermes play];
}
return wasPaused;
}
@end
#pragma clang assume_nonnull end

View file

@ -32,6 +32,7 @@
#import "BGMVLC.h"
#import "BGMVOX.h"
#import "BGMDecibel.h"
#import "BGMHermes.h"
#pragma clang assume_nonnull begin
@ -52,7 +53,8 @@
[BGMVLC class],
[BGMSpotify class],
[BGMiTunes class],
[BGMDecibel class]]
[BGMDecibel class],
[BGMHermes class] ]
userDefaults:defaults];
}

View file

@ -0,0 +1,78 @@
/*
* Hermes.h
*
* Generated with
* sdef /Applications/Hermes.app | sdp -fh --basename Hermes
*/
#import <AppKit/AppKit.h>
#import <ScriptingBridge/ScriptingBridge.h>
@class HermesApplication, HermesSong, HermesStation;
// Legal player states
enum HermesPlayerStates {
HermesPlayerStatesStopped = 'stop' /* Player is stopped */,
HermesPlayerStatesPlaying = 'play' /* Player is playing */,
HermesPlayerStatesPaused = 'paus' /* Player is paused */
};
typedef enum HermesPlayerStates HermesPlayerStates;
/*
* Hermes Suite
*/
// The Pandora player.
@interface HermesApplication : SBApplication
- (SBElementArray<HermesStation *> *) stations;
@property NSInteger playbackVolume; // The current playback volume (0100).
@property HermesPlayerStates playbackState; // The current playback state.
@property (readonly) double playbackPosition; // The current songs playback position, in seconds.
@property (readonly) double currentSongDuration; // The duration (length) of the current song, in seconds.
@property (copy) HermesStation *currentStation; // The currently selected Pandora station.
@property (copy, readonly) HermesSong *currentSong; // The currently playing (or paused) Pandora song (WARNING: This is an invalid reference in current versions of Hermes; you must access the current songs properties individually or as a group directly instead.)
- (void) playpause; // Play the current song if it is paused; pause the current song if it is playing.
- (void) pause; // Pause the currently playing song.
- (void) play; // Resume playing the current song.
- (void) nextSong; // Skip to the next song on the current station.
- (void) thumbsUp; // Tell Pandora you like the current song.
- (void) thumbsDown; // Tell Pandora you dont like the current song.
- (void) tiredOfSong; // Tell Pandora youre tired of the current song.
- (void) increaseVolume; // Increase the playback volume.
- (void) decreaseVolume; // Decrease the playback volume.
- (void) maximizeVolume; // Set the playback volume to its maximum level.
- (void) mute; // Mutes playback, saving the current volume level.
- (void) unmute; // Restores the volume to the level prior to muting.
@end
// A Pandora song (track).
@interface HermesSong : SBObject
@property (copy, readonly) NSString *title; // The songs title.
@property (copy, readonly) NSString *artist; // The songs artist.
@property (copy, readonly) NSString *album; // The songs album.
@property (copy, readonly) NSString *artworkURL; // An image URL for the albums cover artwork.
@property (readonly) NSInteger rating; // The songs numeric rating.
@property (copy, readonly) NSString *albumURL; // A Pandora URL for more information on the album.
@property (copy, readonly) NSString *artistURL; // A Pandora URL for more information on the artist.
@property (copy, readonly) NSString *trackURL; // A Pandora URL for more information on the track.
@end
// A Pandora station.
@interface HermesStation : SBObject
@property (copy, readonly) NSString *name; // The stations name.
@property (copy, readonly) NSString *stationID; // The stations ID.
@end

View file

@ -3,7 +3,7 @@
![](Images/README/FermataIcon.png)
# Background Music
##### OS X audio utility
##### macOS audio utility
![](Images/README/Screenshot.png)
@ -25,10 +25,11 @@ Background Music can pause your music player app when other audio starts playing
that when I'm listening to music and pause it to watch a video or something I always forget to unpause it afterwards. So
this keeps me from wearing headphones for hours listening to nothing.
So far iTunes, [Spotify](https://www.spotify.com), [Decibel](https://sbooth.org/Decibel/),
[VLC](https://www.videolan.org/vlc/) and [VOX](https://coppertino.com/vox/mac) are supported, but adding support for a
music player should only take a few minutes (see `BGMMusicPlayer.h`). If you don't know how to program, or just don't
feel like it, create an issue and I'll try to add it for you.
So far iTunes, [Spotify](https://www.spotify.com), [VLC](https://www.videolan.org/vlc/),
[VOX](https://coppertino.com/vox/mac), [Decibel](https://sbooth.org/Decibel/) and [Hermes](http://hermesapp.org/) are
supported. Adding support for a new music player should only take a few minutes<sup id="a1">[1](#f1)</sup> -- see
(BGMMusicPlayer.h)[BGMApp/BGMApp/Music Players/BGMMusicPlayer.h]. If you don't know how to program, or just don't feel
like it, create an issue and I'll try to add it for you.
## App volumes
@ -110,7 +111,7 @@ change the default device and then change it back again. Failing that, you might
the Sound section in System Preferences, click the Output tab and change your default output device to something other
than Background Music Device. Alternatively, you may Option+Click on the Sound icon in the menu bar to select a different output device.
This happens when OS X remembers that Background Music Device was your default audio device the last time you last
This happens when macOS remembers that Background Music Device was your default audio device the last time you last
used (or didn't use) headphones.
- [A recent Chrome bug](https://bugs.chromium.org/p/chromium/issues/detail?id=557620) can stop Chrome from switching to
Background Music Device after you open Background Music. Chrome's audio will still play, but Background Music won't be
@ -153,3 +154,11 @@ change the default device and then change it back again. Failing that, you might
## License
GPLv2 or later
----
<b id="f1">[1]</b> However, if the music player doesn't support AppleScript, or doesn't support the events Background
Music needs (`isPlaying`, `isPaused`, `play` and `pause`), it can take significantly more effort to add. (And in some
cases would require changes to the music player itself.) [](#a1)