forked from kyleneideck/BackgroundMusic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBGMMusicPlayer.h
156 lines (130 loc) · 7.04 KB
/
BGMMusicPlayer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// 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/>.
//
// BGMMusicPlayer.h
// BGMApp
//
// Copyright © 2016, 2018, 2019 Kyle Neideck
//
// The base classes and protocol for objects that represent a music player app.
//
// To add support for a music player, create a class that implements the BGMMusicPlayer protocol
// and add it to initWithAudioDevices in BGMMusicPlayers.mm.
//
// You'll probably want to subclass BGMMusicPlayerBase and, if the music player supports
// AppleScript, use BGMScriptingBridge. Your class might need to override the icon method if the
// default implementation from BGMMusicPlayerBase doesn't work.
//
// BGMSpotify will probably be the most useful example to follow, but they're all pretty
// similar. The music player classes written so far all use Scripting Bridge to communicate with
// the music player apps (see iTunes.h/Spotify.h) but any other way is fine too.
//
// BGMDriver will use either the music player's bundle ID or PID to match it to the audio it
// plays. (Though using PIDs hasn't been tested yet.)
//
// If you're not sure what bundle ID the music player uses, install a debug build of BGMDriver
// and play something in the music player. The easiest way is to do
// build_and_install.sh -d
// BGMDriver will log the bundle ID to system.log when it becomes aware of the music player.
//
// Local Includes
#import "BGMUserDefaults.h"
// System Includes
#import <Cocoa/Cocoa.h>
#pragma clang assume_nonnull begin
@protocol BGMMusicPlayer <NSObject>
// Classes return an instance of themselves for each music player app they make available in
// BGMApp. So far that's always been a single instance, but that will probably change eventually.
// Most classes don't need to override the default implementation from BGMMusicPlayerBase.
//
// But, for example, a class for custom music players would probably return an instance for each
// custom player the user has created. (Also note that it could return an empty array.)
//
// TODO: I think the return type should actually be NSArray<instancetype>*, but that doesn't seem
// to work. There's a Clang bug about this: https://llvm.org/bugs/show_bug.cgi?id=27323
// (though it hasn't been confirmed yet).
+ (NSArray<id<BGMMusicPlayer>>*) createInstancesWithDefaults:(BGMUserDefaults*)userDefaults;
// We need a unique ID for each music player to store in user defaults. In the most common case,
// classes that provide a static (or at least bounded) number of music players, you can generate
// IDs with uuidgen (the command line tool) and include them in your class as constants. Otherwise,
// you'll probably want to store them in user defaults and load them in createInstancesWithDefaults.
@property (readonly) NSUUID* musicPlayerID;
// The name, tool-tip and icon of the music player, to be used in the UI.
@property (readonly) NSString* name;
@property (readonly) NSString* __nullable toolTip;
@property (readonly) NSImage* __nullable icon;
@property (readonly) NSString* __nullable bundleID;
// Classes will usually ignore this property and leave it nil unless the music player has no
// bundle ID.
//
// TODO: If we ever add a music player class that uses this property, it'll need a way to inform
// BGMDevice of changes. It might be easiest to have BGMMusicPlayers to observe this property,
// on the selected music player, with KVO and update BGMDevice when it changes. Or
// BGMMusicPlayers could pass a pointer to itself to createInstancesWithDefaults.
@property NSNumber* __nullable pid;
// True if this is currently the selected music player.
@property (readonly) BOOL selected;
// The state of the music player.
//
// True if the music player app is open.
@property (readonly, getter=isRunning) BOOL running;
// True if the music player is playing a song or some other user-selected audio file. Note that
// the music player playing audio for UI, notifications, etc. won't make this true (which is why we
// need this property and can't just ask BGMDriver if the music player is playing audio).
@property (readonly, getter=isPlaying) BOOL playing;
// True if the music player has a current/open song (or whatever) and will continue playing it if
// BGMMusicPlayer::unpause is called. Normally because the user was playing a song and they or
// BGMApp paused it.
@property (readonly, getter=isPaused) BOOL paused;
// Called when the user selects this music player.
- (void) wasSelected;
// Called when this was the selected music player and the user just selected a different one.
- (void) wasDeselected;
// Pause the music player. Does nothing if the music player is already paused or isn't running.
// Returns YES if the music player is paused now but wasn't before, returns NO otherwise.
- (BOOL) pause;
// Unpause the music player. Does nothing if the music player is already playing or isn't running.
// Returns YES if the music player is playing now but wasn't before, returns NO otherwise.
- (BOOL) unpause;
@end
@interface BGMMusicPlayerBase : NSObject
- (instancetype) initWithMusicPlayerID:(NSUUID*)musicPlayerID
name:(NSString*)name
bundleID:(NSString* __nullable)bundleID;
- (instancetype) initWithMusicPlayerID:(NSUUID*)musicPlayerID
name:(NSString*)name
toolTip:(NSString*)toolTip
bundleID:(NSString* __nullable)bundleID;
- (instancetype) initWithMusicPlayerID:(NSUUID*)musicPlayerID
name:(NSString*)name
toolTip:(NSString* __nullable)toolTip
bundleID:(NSString* __nullable)bundleID
pid:(NSNumber* __nullable)pid;
// Convenience wrapper around NSUUID's initWithUUIDString. musicPlayerIDString must be a string
// generated by uuidgen (command line tool), e.g. "60BA9739-B6DD-4E6A-8134-51410A45BB84".
+ (NSUUID*) makeID:(NSString*)musicPlayerIDString;
// BGMMusicPlayer default implementations
+ (NSArray<id<BGMMusicPlayer>>*) createInstancesWithDefaults:(BGMUserDefaults*)userDefaults;
@property (readonly) NSImage* __nullable icon;
@property (readonly) NSUUID* musicPlayerID;
@property (readonly) NSString* name;
@property (readonly) NSString* __nullable toolTip;
@property (readonly) NSString* __nullable bundleID;
@property NSNumber* __nullable pid;
@property (readonly) BOOL selected;
- (void) wasSelected;
- (void) wasDeselected;
@end
#pragma clang assume_nonnull end