Lyrics: Implement Lyrics window display and hotkey

Implement Lyrics window display into main app as a popup window panel,
with a main menu hotkey.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
main
Christopher Snowhill 2023-02-23 17:45:59 -08:00
parent 8eaafe8f9b
commit 420d706979
No known key found for this signature in database
5 changed files with 203 additions and 8 deletions

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="LyricsWindowController">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="eSJ-Nv-PBE"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Lyrics" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" visibleAtLaunch="NO" frameAutosaveName="LyricsWindow" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" id="O8B-8Z-Mxc">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" id="O6S-QV-ThM">
<rect key="frame" x="0.0" y="0.0" width="465" height="270"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView wantsLayer="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" findStyle="bar" incrementalSearchingEnabled="YES" id="DKA-ld-0Sh">
<rect key="frame" x="0.0" y="0.0" width="465" height="270"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="465" height="270"/>
<size key="maxSize" width="476" height="10000000"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
<connections>
<binding destination="-2" name="value" keyPath="valueToDisplay.unsyncedlyrics" id="tSj-CA-G4Q">
<dictionary key="options">
<bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/>
<bool key="NSConditionallySetsEditable" value="NO"/>
</dictionary>
</binding>
</connections>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="f77-wI-xOz">
<rect key="frame" x="-100" y="-100" width="225" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="XfW-du-B6L">
<rect key="frame" x="465" y="0.0" width="15" height="270"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
</view>
<point key="canvasLocation" x="126" y="104"/>
</window>
<userDefaultsController representsSharedInstance="YES" id="t5R-DO-d90"/>
</objects>
</document>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -25,17 +25,17 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<splitView dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2123">
<rect key="frame" x="0.0" y="372" width="1135" height="28"/>
<rect key="frame" x="0.0" y="339" width="1135" height="61"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="0.0" verticalLineScroll="24" verticalPageScroll="0.0" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="206" userLabel="Scroll View - Playlist View">
<rect key="frame" x="0.0" y="0.0" width="1135" height="28"/>
<rect key="frame" x="0.0" y="0.0" width="1135" height="61"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="KWC-Ti-8KY">
<rect key="frame" x="0.0" y="0.0" width="1135" height="28"/>
<rect key="frame" x="0.0" y="0.0" width="1135" height="61"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" alternatingRowBackgroundColors="YES" autosaveName="Playlist" rowHeight="18" headerView="1517" viewBased="YES" id="207" customClass="PlaylistView">
<rect key="frame" x="0.0" y="0.0" width="1135" height="11"/>
<rect key="frame" x="0.0" y="0.0" width="1135" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="6"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -680,12 +680,12 @@
</tableCellView>
</prototypeCellViews>
<connections>
<binding destination="1689" name="fontSize" keyPath="values.fontSize" id="36z-Tr-B4G"/>
<binding destination="218" name="value" keyPath="arrangedObjects.sampleRate" id="5lo-d8-LCy">
<dictionary key="options">
<bool key="NSConditionallySetsEditable" value="YES"/>
</dictionary>
</binding>
<binding destination="1689" name="fontSize" keyPath="values.fontSize" id="36z-Tr-B4G"/>
</connections>
</tableColumn>
<tableColumn identifier="bitspersample" editable="NO" width="64" minWidth="32" maxWidth="1024" hidden="YES" id="3no-xo-TpJ" userLabel="Bits Per Sample">
@ -724,12 +724,12 @@
</tableCellView>
</prototypeCellViews>
<connections>
<binding destination="1689" name="fontSize" keyPath="values.fontSize" id="OsB-l4-dFb"/>
<binding destination="218" name="value" keyPath="arrangedObjects.bitsPerSample" id="qVg-Ph-8TQ">
<dictionary key="options">
<bool key="NSConditionallySetsEditable" value="YES"/>
</dictionary>
</binding>
<binding destination="1689" name="fontSize" keyPath="values.fontSize" id="OsB-l4-dFb"/>
</connections>
</tableColumn>
</tableColumns>
@ -1531,6 +1531,11 @@
<action selector="toggleWindow:" target="2422" id="2454"/>
</connections>
</menuItem>
<menuItem title="Show Lyrics" keyEquivalent="L" id="Tkb-7M-OiA">
<connections>
<action selector="toggleWindow:" target="3y4-Q0-Kkl" id="0kv-17-aS6"/>
</connections>
</menuItem>
<menuItem title="Show Spotlight Panel" keyEquivalent="F" id="1853">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
@ -2504,6 +2509,13 @@ Gw
</connections>
</customObject>
<customObject id="Hd4-Wy-Rfl" customClass="AboutWindowController" customModule="Cog" customModuleProvider="target"/>
<customObject id="3y4-Q0-Kkl" customClass="LyricsWindowController">
<connections>
<outlet property="appController" destination="226" id="tbl-VH-JHF"/>
<outlet property="currentEntryController" destination="1897" id="5k1-yb-UNo"/>
<outlet property="playlistSelectionController" destination="2020" id="eLM-rx-mpe"/>
</connections>
</customObject>
</objects>
<resources>
<image name="deadItemsTemplate" width="20" height="20"/>

View File

@ -193,6 +193,8 @@
83AA7D06279EBCAD00087AA4 /* libavutil.57.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83AA7D02279EBC8200087AA4 /* libavutil.57.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
83AA7D07279EBCAF00087AA4 /* libswresample.4.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83AA7D01279EBC8200087AA4 /* libswresample.4.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
83B06704180D579E008E3612 /* MIDI.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83B066A1180D5669008E3612 /* MIDI.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
83B61E2429A8296500CD0580 /* LyricsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 83B61E2229A8296500CD0580 /* LyricsWindow.xib */; };
83B61E2829A82A0200CD0580 /* LyricsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B61E2729A82A0200CD0580 /* LyricsWindowController.m */; };
83B72E3B279045B7006007A3 /* libfdk-aac.2.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83B72E2A279044F6006007A3 /* libfdk-aac.2.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
83BC5AB220E4C87100631CD4 /* DualWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BC5AB020E4C87100631CD4 /* DualWindow.m */; };
83BC5ABF20E4CE7A00631CD4 /* InfoInspector.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17D1B0D00F6320EA00694C57 /* InfoInspector.xib */; };
@ -1070,6 +1072,9 @@
83AA7D03279EBC8300087AA4 /* libavformat.59.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libavformat.59.dylib; path = ThirdParty/ffmpeg/lib/libavformat.59.dylib; sourceTree = "<group>"; };
83AB9031237CEFD300A433D5 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
83B0669C180D5668008E3612 /* MIDI.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MIDI.xcodeproj; path = Plugins/MIDI/MIDI.xcodeproj; sourceTree = "<group>"; };
83B61E2329A8296500CD0580 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LyricsWindow.xib; sourceTree = "<group>"; };
83B61E2629A82A0200CD0580 /* LyricsWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LyricsWindowController.h; sourceTree = "<group>"; };
83B61E2729A82A0200CD0580 /* LyricsWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LyricsWindowController.m; sourceTree = "<group>"; };
83B72E2A279044F6006007A3 /* libfdk-aac.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libfdk-aac.2.dylib"; path = "ThirdParty/fdk-aac/lib/libfdk-aac.2.dylib"; sourceTree = "<group>"; };
83BC5AB020E4C87100631CD4 /* DualWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DualWindow.m; path = Window/DualWindow.m; sourceTree = "<group>"; };
83BC5AB120E4C87100631CD4 /* DualWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DualWindow.h; path = Window/DualWindow.h; sourceTree = "<group>"; };
@ -1186,6 +1191,7 @@
17DDF6400E0CB6F100A2E4AD /* FileTree */,
830C37A227B95E6000E02BB0 /* Equalizer */,
17D1B0FE0F63252900694C57 /* InfoInspector */,
83B61E2529A8299A00CD0580 /* LyricsWindow */,
569C52C50D5F2BD500BDBDC9 /* Spotlight */,
17E0D5F60F520F42005B6FED /* Transformers */,
177EC0110B8BC2CF0000BC8C /* Utils */,
@ -1612,6 +1618,7 @@
178456C00F6320B5007E8021 /* SpotlightPanel.xib */,
17E41E060C130DFF00AC744D /* Credits.html */,
17D1B1DA0F6330D400694C57 /* Feedback.xib */,
83B61E2229A8296500CD0580 /* LyricsWindow.xib */,
836DF61D298F7F6E00CD0580 /* Scenes.scnassets */,
);
name = Resources;
@ -1910,6 +1917,15 @@
name = Products;
sourceTree = "<group>";
};
83B61E2529A8299A00CD0580 /* LyricsWindow */ = {
isa = PBXGroup;
children = (
83B61E2629A82A0200CD0580 /* LyricsWindowController.h */,
83B61E2729A82A0200CD0580 /* LyricsWindowController.m */,
);
path = LyricsWindow;
sourceTree = "<group>";
};
83BB13AE20E4E38E00723731 /* Products */ = {
isa = PBXGroup;
children = (
@ -2538,6 +2554,7 @@
83BC5AC320E4CE8D00631CD4 /* SpotlightPanel.xib in Resources */,
83BC5AC220E4CE8A00631CD4 /* FileTree.xib in Resources */,
83BC5AC120E4CE8700631CD4 /* OpenURLPanel.xib in Resources */,
83B61E2429A8296500CD0580 /* LyricsWindow.xib in Resources */,
0A1B412C286F6301008A6A44 /* Localizable.stringsdict in Resources */,
83BC5AC020E4CE7D00631CD4 /* MainMenu.xib in Resources */,
83BC5ABF20E4CE7A00631CD4 /* InfoInspector.xib in Resources */,
@ -2686,6 +2703,7 @@
56462EAF0D6341F6000AB68C /* SpotlightTransformers.m in Sources */,
830C37A527B95EB300E02BB0 /* EqualizerWindowController.m in Sources */,
832CFC562851AA8B002AC26F /* SpectrumViewCG.m in Sources */,
83B61E2829A82A0200CD0580 /* LyricsWindowController.m in Sources */,
56462EB20D634206000AB68C /* SpotlightPlaylistController.m in Sources */,
07E18DF30D62B38400BB0E11 /* NSArray+ShuffleUtils.m in Sources */,
56C63D910D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m in Sources */,
@ -3049,6 +3067,14 @@
name = SpectrumWindow.xib;
sourceTree = "<group>";
};
83B61E2229A8296500CD0580 /* LyricsWindow.xib */ = {
isa = PBXVariantGroup;
children = (
83B61E2329A8296500CD0580 /* Base */,
);
name = LyricsWindow.xib;
sourceTree = "<group>";
};
8E7575D909F31E930080F1EE /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (

View File

@ -0,0 +1,28 @@
//
// LyricsWindowController.h
// Cog
//
// Created by Christopher Snowhill on 2/23/23.
//
#import <Cocoa/Cocoa.h>
#import "AppController.h"
NS_ASSUME_NONNULL_BEGIN
@interface LyricsWindowController : NSWindowController {
IBOutlet id playlistSelectionController;
IBOutlet id currentEntryController;
IBOutlet AppController *appController;
id __unsafe_unretained valueToDisplay;
}
@property(assign) id valueToDisplay;
- (IBAction)toggleWindow:(id)sender;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,63 @@
//
// LyricsWindowController.m
// Cog
//
// Created by Christopher Snowhill on 2/23/23.
//
#import "LyricsWindowController.h"
#import "AppController.h"
#import "PlaylistEntry.h"
@interface LyricsWindowController ()
@end
@implementation LyricsWindowController
static void *kLyricsWindowControllerContext = &kLyricsWindowControllerContext;
@synthesize valueToDisplay;
- (id)init {
return [super initWithWindowNibName:@"LyricsWindow"];
}
- (void)awakeFromNib {
[playlistSelectionController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:kLyricsWindowControllerContext];
[currentEntryController addObserver:self forKeyPath:@"content" options:NSKeyValueObservingOptionNew context:kLyricsWindowControllerContext];
[appController addObserver:self forKeyPath:@"miniMode" options:NSKeyValueObservingOptionNew context:kLyricsWindowControllerContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(context == kLyricsWindowControllerContext) {
// Avoid "selection" because it creates a proxy that's hard to reason with when we don't need to write.
PlaylistEntry *currentSelection = [[playlistSelectionController selectedObjects] firstObject];
if(currentSelection != NULL) {
[self setValueToDisplay:currentSelection];
} else {
[self setValueToDisplay:[currentEntryController content]];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (IBAction)toggleWindow:(id)sender {
if([[self window] isVisible])
[[self window] orderOut:self];
else {
if([NSApp mainWindow]) {
NSRect rect = [[NSApp mainWindow] frame];
// Align Lyrics Window to the right of Main Window.
NSPoint point = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
[[self window] setFrameTopLeftPoint:point];
}
[self showWindow:self];
}
}
@end