[vlc-commits] [Git][videolan/vlc][master] 33 commits: macosx: Add VLCLibraryAudioGroupHeaderView XIB

Steve Lhomme (@robUx4) gitlab at videolan.org
Wed Jul 26 10:39:22 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
741102ea by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add VLCLibraryAudioGroupHeaderView XIB

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
7acb06e3 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add initial contents of VLCLibraryAudioGroupHeader UI

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
69228065 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add VLCLibraryAudioGroupHeaderView class

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
e37d2c3e by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Wrap VLCLibraryAudioGroupHeaderView xib in an NSView, use the relevant ObjC class

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
bbdb1d91 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add VLCLibraryAudioGroupHeaderViewIdentifier

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
984a4733 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add convenience method to setup collection views for use with VLCLibraryAudioGroupDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
b26d8a8b by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add default header size class property to VLCLibraryAudioGroupHeaderView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
7480a822 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add IBOutlets for major UI elements in VLCLibraryAudioGroupHeaderView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
412538bb by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Keep track of relevant views in VLCLibraryAudioGroupDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
998b7f6a by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Make VLCLibraryAudioDataSource setupCollectionView static

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
2136e717 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Handle updating of represented albums in VLCLibraryAudioGroupDataSource within it, not in VLCLibraryAudioDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
332e9fb1 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Handle the album views for selected audio groups inside VLCLibraryAudioGroupDataSource instead of VLCLibraryAudioDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
351c11d1 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Correctly reimplement groupSelectionDoubleClickAction in VLCLibraryAudioDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
81230429 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add code to set represented item and details on VLCLibraryAudioGroupHeaderView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
f7d1b3ac by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Display the new audio group header view in the selection views

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
bf0fd735 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Make displayAllArtistsGenresTableEntry internal property

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
29476552 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Implement revealInFinder method for VLCMediaLibraryDummyItem

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
fc482098 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Add a VLCMediaLibraryAllItemsGroup data type for all items entry

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
4215525b by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Take object with VLCMediaLibraryAudioGroupProtocol instead of abstract class in audio group classes

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
9e287442 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Prevent crashing in VLCLibraryAudioGroupHeaderView when represented item is nil

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
1685dd36 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Simplify handling of 'all items' item in audio data source by treating dummy item like any other item

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
87f7af8f by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Fix warning sort descriptor warning

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
30319ea4 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Fix crash on swich to songs view in audio library

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
be39137e by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Ensure deselection of items when switching audio library segment in VLCLibraryAudioDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
2ec086f9 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Set nil audio group when invalid selected row is acquired in VLCLibraryAudioDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
448b7ce2 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Make representedListOfAlbums a private, atomic property of VLCLibraryAudioGroupDataSource

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
37e30be4 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Protect the libraryAtX methods from bad row or idnex path values

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
c251424c by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Ensure play button in VLCLibraryAudioGroupHeaderView has correct accent color

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
72e13630 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Make play and queue functions in VLCLibraryAudioGroupHeader functional

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
2e922484 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Redesign audio header view to be more spacious, have proper background

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
a72e91d0 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Pin header to top in audio group selection view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
b5dc6f57 by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Resize audio header view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
3917282d by Claudio Cambra at 2023-07-26T10:19:25+00:00
macosx: Fix positioning of pinned headers and footers in VLCLibraryCollectionViewFlowLayout

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -


16 changed files:

- extras/package/macosx/VLC.xcodeproj/project.pbxproj
- modules/gui/macosx/Makefile.am
- + modules/gui/macosx/UI/VLCLibraryAudioGroupHeaderView.xib
- modules/gui/macosx/library/VLCLibraryCollectionViewFlowLayout.m
- modules/gui/macosx/library/VLCLibraryDataTypes.h
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/audio-library/VLCLibraryAlbumTracksDataSource.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.m
- + modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.h
- + modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
- modules/gui/macosx/library/audio-library/VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewContainerViewDataSource.m


Changes:

=====================================
extras/package/macosx/VLC.xcodeproj/project.pbxproj
=====================================
@@ -103,6 +103,7 @@
 		537976BA2A4319330036827E /* VLCSettingTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 537976B82A4319330036827E /* VLCSettingTextField.m */; };
 		5387FFF52A15127100A3A70A /* NSWindow+VLCAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5387FFF42A15127100A3A70A /* NSWindow+VLCAdditions.m */; };
 		538A7EDA29A63EE40068AD4F /* VLCFullVideoViewWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 538A7ED929A63EE40068AD4F /* VLCFullVideoViewWindow.m */; };
+		538DC4E32A6B69B50082DECD /* VLCLibraryAudioGroupHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 538DC4E22A6B69B50082DECD /* VLCLibraryAudioGroupHeaderView.m */; };
 		53903D3A29576ED500D0B308 /* VLCLibraryAudioGroupDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 53903D3929576ED500D0B308 /* VLCLibraryAudioGroupDataSource.m */; };
 		539BA79F298C726200918C36 /* VLCAspectRatioRetainingVideoWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 539BA79E298C726200918C36 /* VLCAspectRatioRetainingVideoWindow.m */; };
 		539F114B29E83A4200F13460 /* VLCLibraryTwoPaneSplitViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 539F114A29E83A4200F13460 /* VLCLibraryTwoPaneSplitViewDelegate.m */; };
@@ -319,6 +320,8 @@
 		5387FFF42A15127100A3A70A /* NSWindow+VLCAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSWindow+VLCAdditions.m"; sourceTree = "<group>"; };
 		538A7ED829A63EE40068AD4F /* VLCFullVideoViewWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCFullVideoViewWindow.h; sourceTree = "<group>"; };
 		538A7ED929A63EE40068AD4F /* VLCFullVideoViewWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCFullVideoViewWindow.m; sourceTree = "<group>"; };
+		538DC4E22A6B69B50082DECD /* VLCLibraryAudioGroupHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryAudioGroupHeaderView.m; sourceTree = "<group>"; };
+		538DC4E42A6B69C00082DECD /* VLCLibraryAudioGroupHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCLibraryAudioGroupHeaderView.h; sourceTree = "<group>"; };
 		53903D3829576ED500D0B308 /* VLCLibraryAudioGroupDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryAudioGroupDataSource.h; sourceTree = "<group>"; };
 		53903D3929576ED500D0B308 /* VLCLibraryAudioGroupDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryAudioGroupDataSource.m; sourceTree = "<group>"; };
 		539BA79D298C726200918C36 /* VLCAspectRatioRetainingVideoWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCAspectRatioRetainingVideoWindow.h; sourceTree = "<group>"; };
@@ -340,6 +343,7 @@
 		53B447F3293BB47A00857588 /* VLCLibraryVideoTableViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryVideoTableViewDataSource.m; sourceTree = "<group>"; };
 		53B447F4293BB47A00857588 /* VLCLibraryVideoGroupDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryVideoGroupDescriptor.m; sourceTree = "<group>"; };
 		53B447F5293BB47B00857588 /* VLCLibraryVideoCollectionViewsStackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCLibraryVideoCollectionViewsStackViewController.h; sourceTree = "<group>"; };
+		53BFB1E02A6A72160065EA7A /* VLCLibraryAudioGroupHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VLCLibraryAudioGroupHeaderView.xib; sourceTree = "<group>"; };
 		53ED472129C74D1F00795DB1 /* VLCLibraryAudioTableViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryAudioTableViewDelegate.h; sourceTree = "<group>"; };
 		53ED472229C74D1F00795DB1 /* VLCLibraryAudioTableViewDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryAudioTableViewDelegate.m; sourceTree = "<group>"; };
 		53ED472429C78FE700795DB1 /* VLCLibraryAudioGroupTableViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryAudioGroupTableViewDelegate.h; sourceTree = "<group>"; };
@@ -1372,6 +1376,8 @@
 		5325C5742930026600B2B63A /* audio-library */ = {
 			isa = PBXGroup;
 			children = (
+				538DC4E42A6B69C00082DECD /* VLCLibraryAudioGroupHeaderView.h */,
+				538DC4E22A6B69B50082DECD /* VLCLibraryAudioGroupHeaderView.m */,
 				5325C57C29302E6800B2B63A /* VLCLibraryAudioViewController.h */,
 				5325C57B29302E6800B2B63A /* VLCLibraryAudioViewController.m */,
 				7DE82E7722843781002D341A /* VLCLibraryAlbumTableCellView.h */,
@@ -1832,6 +1838,7 @@
 				6B82240B1E4D2A9000833BE1 /* VLCInformationWindow.xib */,
 				539F116A29F9756000F13460 /* VLCMainVideoViewAudioMediaDecorativeView.xib */,
 				7DE82E7A228437AA002D341A /* VLCLibraryAlbumTableCellView.xib */,
+				53BFB1E02A6A72160065EA7A /* VLCLibraryAudioGroupHeaderView.xib */,
 				536283FD2911476A00640C15 /* VLCLibraryCollectionViewAlbumSupplementaryDetailView.xib */,
 				536283FB2911476A00640C15 /* VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.xib */,
 				7D0F64052202047900FDB91F /* VLCLibraryCollectionViewItem.xib */,
@@ -2078,6 +2085,7 @@
 				533B5D2C29CF94C6003DE887 /* VLCBookmarksTableViewDataSource.m in Sources */,
 				1C3113D31E508C6900D4DD76 /* VLCResumeDialogController.m in Sources */,
 				7D2FFA40227B8A5B0085D649 /* VLCLinearProgressIndicator.m in Sources */,
+				538DC4E32A6B69B50082DECD /* VLCLibraryAudioGroupHeaderView.m in Sources */,
 				7DFBDCB1226A518400B700A5 /* VLCLibraryMenuController.m in Sources */,
 				536283F8291146BC00640C15 /* VLCLibrarySongTableCellView.m in Sources */,
 				1C3113D51E508C6900D4DD76 /* VLCTextfieldPanelController.m in Sources */,


=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -163,6 +163,8 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m \
 	gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.h \
 	gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.m \
+	gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.h \
+	gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.m \
 	gui/macosx/library/audio-library/VLCLibraryAudioGroupTableViewDelegate.h \
 	gui/macosx/library/audio-library/VLCLibraryAudioGroupTableViewDelegate.m \
 	gui/macosx/library/audio-library/VLCLibraryAudioTableViewDelegate.h \
@@ -400,6 +402,7 @@ libmacosx_plugin_la_XIB_SOURCES = \
 	gui/macosx/UI/VLCCustomCropARPanel.xib \
 	gui/macosx/UI/VLCDetachedAudioWindow.xib \
 	gui/macosx/UI/VLCLibraryAlbumTableCellView.xib \
+	gui/macosx/UI/VLCLibraryAudioGroupHeaderView.xib \
 	gui/macosx/UI/VLCLibraryWindow.xib \
 	gui/macosx/UI/VLCLibraryTableCellView.xib \
 	gui/macosx/UI/VLCPlaylistTableCellView.xib \


=====================================
modules/gui/macosx/UI/VLCLibraryAudioGroupHeaderView.xib
=====================================
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView translatesAutoresizingMaskIntoConstraints="NO" id="E6K-GD-bgu" customClass="VLCLibraryAudioGroupHeaderView">
+            <rect key="frame" x="0.0" y="0.0" width="730" height="86"/>
+            <subviews>
+                <box boxType="custom" borderType="line" cornerRadius="5" title="Box" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="dxP-Cv-lN2">
+                    <rect key="frame" x="0.0" y="0.0" width="730" height="86"/>
+                    <view key="contentView" id="XfC-Xr-mxJ">
+                        <rect key="frame" x="1" y="1" width="728" height="84"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    </view>
+                    <color key="borderColor" name="separatorColor" catalog="System" colorSpace="catalog"/>
+                    <color key="fillColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+                </box>
+                <stackView distribution="fill" orientation="vertical" alignment="leading" spacing="10" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Si-IF-hfH">
+                    <rect key="frame" x="10" y="10" width="710" height="66"/>
+                    <subviews>
+                        <customView verticalHuggingPriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="Yyj-ln-1hz">
+                            <rect key="frame" x="0.0" y="26" width="710" height="40"/>
+                            <subviews>
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VGp-RV-Jl4">
+                                    <rect key="frame" x="-2" y="6" width="144" height="28"/>
+                                    <textFieldCell key="cell" lineBreakMode="clipping" title="Audio Group" id="96R-yZ-Dap">
+                                        <font key="font" metaFont="systemBold" size="24"/>
+                                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </textFieldCell>
+                                </textField>
+                                <stackView distribution="fill" orientation="horizontal" alignment="top" spacing="5" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eE7-fJ-MtS">
+                                    <rect key="frame" x="553" y="6" width="157" height="28"/>
+                                    <subviews>
+                                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UDD-gH-RDW">
+                                            <rect key="frame" x="-6" y="-6" width="88" height="40"/>
+                                            <buttonCell key="cell" type="push" title="Play" bezelStyle="rounded" image="play.fill" catalog="system" imagePosition="leading" alignment="center" controlSize="large" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="1xa-VB-LBX">
+                                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                <font key="font" metaFont="system"/>
+                                            </buttonCell>
+                                            <color key="bezelColor" name="VLCAccentColor"/>
+                                            <connections>
+                                                <action selector="play:" target="E6K-GD-bgu" id="vp4-Ar-psi"/>
+                                            </connections>
+                                        </button>
+                                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Baf-bX-D7M">
+                                            <rect key="frame" x="75" y="-6" width="88" height="40"/>
+                                            <buttonCell key="cell" type="push" title="Queue" bezelStyle="rounded" image="NSAddTemplate" imagePosition="leading" alignment="center" controlSize="large" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="hql-tL-GoL">
+                                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                <font key="font" metaFont="system"/>
+                                            </buttonCell>
+                                            <connections>
+                                                <action selector="enqueue:" target="E6K-GD-bgu" id="MmL-OA-W6A"/>
+                                            </connections>
+                                        </button>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="UDD-gH-RDW" firstAttribute="centerY" secondItem="eE7-fJ-MtS" secondAttribute="centerY" id="7pl-Xu-lre"/>
+                                        <constraint firstItem="Baf-bX-D7M" firstAttribute="centerY" secondItem="eE7-fJ-MtS" secondAttribute="centerY" id="AMr-ZS-8Ot"/>
+                                        <constraint firstItem="UDD-gH-RDW" firstAttribute="width" secondItem="Baf-bX-D7M" secondAttribute="width" id="N5Y-W0-Y5P"/>
+                                        <constraint firstAttribute="width" constant="157" id="hWf-p4-ES0"/>
+                                    </constraints>
+                                    <visibilityPriorities>
+                                        <integer value="1000"/>
+                                        <integer value="1000"/>
+                                    </visibilityPriorities>
+                                    <customSpacing>
+                                        <real value="3.4028234663852886e+38"/>
+                                        <real value="3.4028234663852886e+38"/>
+                                    </customSpacing>
+                                </stackView>
+                            </subviews>
+                            <constraints>
+                                <constraint firstAttribute="trailing" secondItem="eE7-fJ-MtS" secondAttribute="trailing" id="Ko4-Yr-Zzj"/>
+                                <constraint firstItem="VGp-RV-Jl4" firstAttribute="leading" secondItem="Yyj-ln-1hz" secondAttribute="leading" id="Oed-yO-cxQ"/>
+                                <constraint firstAttribute="height" constant="40" id="UZ9-lj-BXD"/>
+                                <constraint firstItem="eE7-fJ-MtS" firstAttribute="centerY" secondItem="Yyj-ln-1hz" secondAttribute="centerY" id="XWb-3l-7qH"/>
+                                <constraint firstItem="VGp-RV-Jl4" firstAttribute="centerY" secondItem="Yyj-ln-1hz" secondAttribute="centerY" id="fgu-OU-KwU"/>
+                                <constraint firstItem="eE7-fJ-MtS" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="VGp-RV-Jl4" secondAttribute="trailing" constant="10" id="fsv-ju-hNO"/>
+                            </constraints>
+                        </customView>
+                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8Fd-yT-2AG">
+                            <rect key="frame" x="-2" y="0.0" width="714" height="16"/>
+                            <textFieldCell key="cell" lineBreakMode="clipping" title="0 albums, 0 songs" id="Tmx-ap-c2a">
+                                <font key="font" usesAppearanceFont="YES"/>
+                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="Yyj-ln-1hz" firstAttribute="leading" secondItem="0Si-IF-hfH" secondAttribute="leading" id="Ci0-Wg-TUY"/>
+                        <constraint firstItem="8Fd-yT-2AG" firstAttribute="leading" secondItem="0Si-IF-hfH" secondAttribute="leading" id="Kyd-AH-vSN"/>
+                        <constraint firstAttribute="trailing" secondItem="Yyj-ln-1hz" secondAttribute="trailing" id="LeP-os-gHu"/>
+                        <constraint firstAttribute="trailing" secondItem="8Fd-yT-2AG" secondAttribute="trailing" id="VyH-Uu-36X"/>
+                    </constraints>
+                    <visibilityPriorities>
+                        <integer value="1000"/>
+                        <integer value="1000"/>
+                    </visibilityPriorities>
+                    <customSpacing>
+                        <real value="3.4028234663852886e+38"/>
+                        <real value="3.4028234663852886e+38"/>
+                    </customSpacing>
+                </stackView>
+            </subviews>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="dxP-Cv-lN2" secondAttribute="bottom" id="3Z8-gS-rVm"/>
+                <constraint firstItem="dxP-Cv-lN2" firstAttribute="leading" secondItem="E6K-GD-bgu" secondAttribute="leading" id="IVx-Qi-Hdt"/>
+                <constraint firstItem="dxP-Cv-lN2" firstAttribute="top" secondItem="E6K-GD-bgu" secondAttribute="top" id="Rbe-hF-1hS"/>
+                <constraint firstItem="0Si-IF-hfH" firstAttribute="top" secondItem="E6K-GD-bgu" secondAttribute="top" constant="10" id="fw0-cv-Ofa"/>
+                <constraint firstAttribute="trailing" secondItem="dxP-Cv-lN2" secondAttribute="trailing" id="iTk-8w-5CF"/>
+                <constraint firstAttribute="trailing" secondItem="0Si-IF-hfH" secondAttribute="trailing" constant="10" id="mM3-Iy-sSh"/>
+                <constraint firstAttribute="bottom" secondItem="0Si-IF-hfH" secondAttribute="bottom" constant="10" id="sUV-bu-8ug"/>
+                <constraint firstItem="0Si-IF-hfH" firstAttribute="leading" secondItem="E6K-GD-bgu" secondAttribute="leading" constant="10" id="vM8-9F-b9Q"/>
+            </constraints>
+            <connections>
+                <outlet property="detailTextField" destination="8Fd-yT-2AG" id="VVh-Xd-Ma1"/>
+                <outlet property="playButton" destination="UDD-gH-RDW" id="Cvj-Zy-lA5"/>
+                <outlet property="queueButton" destination="Baf-bX-D7M" id="LXJ-9K-2zU"/>
+                <outlet property="titleTextField" destination="VGp-RV-Jl4" id="G9K-eO-d5s"/>
+            </connections>
+            <point key="canvasLocation" x="-588" y="-314"/>
+        </customView>
+    </objects>
+    <resources>
+        <image name="NSAddTemplate" width="18" height="17"/>
+        <image name="play.fill" catalog="system" width="12" height="13"/>
+        <namedColor name="VLCAccentColor">
+            <color red="1" green="0.37999999523162842" blue="0.039999999105930328" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>


=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewFlowLayout.m
=====================================
@@ -231,7 +231,16 @@ static CVReturn detailViewAnimationCallback(CVDisplayLinkRef displayLink,
     // Computed attributes from parent
     NSMutableArray<__kindof NSCollectionViewLayoutAttributes *> *layoutAttributesArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
     for (int i = 0; i < layoutAttributesArray.count; i++) {
-        NSCollectionViewLayoutAttributes *attributes = layoutAttributesArray[i];
+        NSCollectionViewLayoutAttributes * const attributes = layoutAttributesArray[i];
+        NSString * const elementKind = attributes.representedElementKind;
+        
+        if (@available(macOS 10.12, *)) {
+            if (([elementKind isEqualToString:NSCollectionElementKindSectionHeader] && self.sectionHeadersPinToVisibleBounds) || 
+                ([elementKind isEqualToString:NSCollectionElementKindSectionFooter] && self.sectionFootersPinToVisibleBounds)) {
+                continue;
+            }
+        }
+
         [attributes setFrame:[self frameForDisplacedAttributes:attributes]];
         layoutAttributesArray[i] = attributes;
     }
@@ -318,7 +327,8 @@ static CVReturn detailViewAnimationCallback(CVDisplayLinkRef displayLink,
 
 # pragma mark - Calculation of displaced frame attributes
 
-- (NSRect)frameForDisplacedAttributes:(NSCollectionViewLayoutAttributes *)inAttributes {
+- (NSRect)frameForDisplacedAttributes:(NSCollectionViewLayoutAttributes *)inAttributes
+{
     if(inAttributes == nil) {
         return NSZeroRect;
     }


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.h
=====================================
@@ -257,4 +257,10 @@ extern const long long int VLCMediaLibraryMediaItemDurationDenominator;
 
 @end
 
+ at interface VLCMediaLibraryAllItemsGroup : VLCMediaLibraryDummyItem<VLCMediaLibraryAudioGroupProtocol>
+
+- (nullable instancetype)initWithDisplayString:(NSString *)displayString;
+
+ at end
+
 NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -26,6 +26,8 @@
 #import "extensions/NSString+Helpers.h"
 #import "library/VLCInputItem.h"
 #import "library/VLCLibraryImageCache.h"
+#import "library/VLCLibraryController.h"
+#import "library/VLCLibraryModel.h"
 
 #import <vlc_url.h>
 
@@ -1177,7 +1179,6 @@ static NSArray<VLCMediaLibraryArtist *> *fetchArtistsForLibraryItem(library_arti
 @synthesize smallArtworkGenerated = _smallArtworkGenerated;
 @synthesize smallArtworkMRL = _smallArtworkMRL;
 
-
 - (instancetype)initWithDisplayString:(NSString*)displayString
                      withDetailString:(NSString*)detailString
 {
@@ -1193,8 +1194,36 @@ static NSArray<VLCMediaLibraryArtist *> *fetchArtistsForLibraryItem(library_arti
     return self;
 }
 
-- (void)iterateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull))mediaItemBlock {
+- (void)iterateMediaItemsWithBlock:(nonnull void (^)(VLCMediaLibraryMediaItem * _Nonnull))mediaItemBlock
+{
     return;
 }
 
+- (void)revealInFinder
+{
+    return;
+}
+
+ at end
+
+ at implementation VLCMediaLibraryAllItemsGroup
+
+ at synthesize albums = _albums;
+ at synthesize artists = _artists;
+ at synthesize numberOfTracks = _numberOfTracks;
+ at synthesize tracksAsMediaItems = _tracksAsMediaItems;
+
+- (instancetype)initWithDisplayString:(NSString *)displayString
+{
+    VLCLibraryModel * const libraryModel = VLCMain.sharedInstance.libraryController.libraryModel;
+    _albums = libraryModel.listOfAlbums;
+    _artists = libraryModel.listOfArtists;
+    _numberOfTracks = libraryModel.numberOfAudioMedia;
+    _tracksAsMediaItems = libraryModel.listOfAudioMedia;
+
+    NSString * const detailString = [NSString stringWithFormat:_NS("%li albums, %li songs"), _albums.count, _tracksAsMediaItems.count];
+
+    return [super initWithDisplayString:displayString withDetailString:detailString];
+}
+
 @end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAlbumTracksDataSource.m
=====================================
@@ -82,6 +82,10 @@ const CGFloat VLCLibraryTracksRowHeight = 40.;
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtRow:(NSInteger)row
                                        forTableView:(NSTableView *)tableView
 {
+    if (row < 0 || row >= self.tracks.count) {
+        return nil;
+    }
+
     return self.tracks[row];
 }
 


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h
=====================================
@@ -59,16 +59,14 @@ extern NSString * const VLCLibraryYearSortDescriptorKey;
 @property (readwrite, assign) VLCLibraryModel *libraryModel;
 @property (readwrite, assign) VLCLibraryAudioGroupDataSource *audioGroupDataSource;
 @property (readwrite, assign) NSTableView *collectionSelectionTableView;
- at property (readwrite, assign) NSTableView *groupSelectionTableView;
 @property (readwrite, assign) NSTableView *songsTableView;
 @property (readwrite, assign) NSCollectionView *collectionView;
 @property (readwrite, assign) NSTableView *gridModeListTableView;
- at property (readwrite, assign) NSCollectionView *gridModeListSelectionCollectionView;
 
 @property (nonatomic, readwrite, assign) VLCAudioLibrarySegment audioLibrarySegment;
 
++ (void)setupCollectionView:(NSCollectionView *)collectionView;
 - (void)setup;
-- (void)setupCollectionView:(NSCollectionView *)collectionView;
 
 - (void)reloadData;
 - (void)tableView:(NSTableView * const)tableView selectRow:(NSInteger)row;


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
=====================================
@@ -80,6 +80,7 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 }
 
 @property (readwrite, atomic) NSArray *displayedCollection;
+ at property (readonly) BOOL displayAllArtistsGenresTableEntry;
 
 @end
 
@@ -345,12 +346,6 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
                                                               forTableView:_collectionSelectionTableView];
     }
 
-    const NSInteger groupSelectionTableViewRow = _groupSelectionTableView.selectedRow;
-    if(groupSelectionTableViewRow >= 0 && !_groupSelectionTableView.hidden) {
-        _selectedGroupSelectionTableViewItem = [self libraryItemAtRow:groupSelectionTableViewRow
-                                                         forTableView:_groupSelectionTableView];
-    }
-
     const NSInteger songsTableViewRow = _songsTableView.selectedRow;
     if(songsTableViewRow >= 0 && !_songsTableView.hidden) {
         _selectedSongTableViewItem = [self libraryItemAtRow:songsTableViewRow
@@ -372,7 +367,6 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 {
     [self restoreCollectionViewSelectionState];
     [self restoreCollectionSelectionTableViewSelectionState];
-    [self restoreGroupSelectionTableViewSelectionState];
     [self restoreSongTableViewSelectionState];
 }
 
@@ -422,13 +416,6 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
     _selectedCollectionSelectionTableViewItem = nil;
 }
 
-- (void)restoreGroupSelectionTableViewSelectionState
-{
-    [self restoreSelectionStateForTableView:_groupSelectionTableView
-                           withSelectedItem:_selectedGroupSelectionTableViewItem];
-    _selectedGroupSelectionTableViewItem = nil;
-}
-
 - (void)restoreSongTableViewSelectionState
 {
     [self restoreSelectionStateForTableView:_songsTableView
@@ -438,14 +425,13 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 
 - (void)setup
 {
-    [self setupCollectionView:_collectionView];
-    [self setupCollectionView:_gridModeListSelectionCollectionView];
+    [VLCLibraryAudioDataSource setupCollectionView:_collectionView];
     [self setupTableViews];
 
     _audioLibrarySegment = -1; // Force setAudioLibrarySegment to do something always on first try
 }
 
-- (void)setupCollectionView:(NSCollectionView *)collectionView
++ (void)setupCollectionView:(NSCollectionView *)collectionView
 {
     [collectionView registerClass:[VLCLibraryCollectionViewItem class] forItemWithIdentifier:VLCLibraryCellIdentifier];
 
@@ -467,14 +453,11 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 
 - (void)setupTableViews
 {
-    _groupSelectionTableView.target = self;
-    _groupSelectionTableView.doubleAction = @selector(groubSelectionDoubleClickAction:);
-
     _collectionSelectionTableView.target = self;
     _collectionSelectionTableView.doubleAction = @selector(collectionSelectionDoubleClickAction:);
 
     _gridModeListTableView.target = self;
-    _gridModeListTableView.doubleAction = @selector(groubSelectionDoubleClickAction:);
+    _gridModeListTableView.doubleAction = @selector(groupSelectionDoubleClickAction:);
 
     [self setupSongsTableView];
 }
@@ -526,12 +509,12 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 
 - (void)setupExistingSortForTableView:(NSTableView *)tableView
 {
-    const VLCLibraryController * const libraryController = VLCMain.sharedInstance.libraryController;
+    VLCLibraryController * const libraryController = VLCMain.sharedInstance.libraryController;
     const vlc_ml_sorting_criteria_t existingSortCriteria = libraryController.lastSortingCriteria;
 
-    NSString *sortDescriptorKey = [self sortDescriptorKeyFromVlcMlSortingCriteria:existingSortCriteria];
-    const NSSortDescriptor * const sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortDescriptorKey
-                                                                                ascending:!libraryController.descendingLibrarySorting];
+    NSString * const sortDescriptorKey = [self sortDescriptorKeyFromVlcMlSortingCriteria:existingSortCriteria];
+    NSSortDescriptor * const sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortDescriptorKey
+                                                                          ascending:!libraryController.descendingLibrarySorting];
 
     tableView.sortDescriptors = @[sortDescriptor];
 }
@@ -568,11 +551,6 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
         [collectionViewFlowLayout resetLayout];
     }
 
-    VLCLibraryCollectionViewFlowLayout *gridModeListSelectionCollectionViewFlowLayout = (VLCLibraryCollectionViewFlowLayout *)_gridModeListSelectionCollectionView.collectionViewLayout;
-    if (gridModeListSelectionCollectionViewFlowLayout) {
-        [gridModeListSelectionCollectionViewFlowLayout resetLayout];
-    }
-
     operation();
     [self setupExistingSortForTableView:_songsTableView];
 }
@@ -583,12 +561,25 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
         [self retainSelectedMediaItem];
         self.displayedCollection = [self collectionToDisplay];
 
+        if (self.displayAllArtistsGenresTableEntry) {
+            NSMutableArray * const mutableCollectionCopy = self.displayedCollection.mutableCopy;
+            VLCMediaLibraryAllItemsGroup *group;
+
+            if (_currentParentType == VLC_ML_PARENT_GENRE) {
+                group = [[VLCMediaLibraryAllItemsGroup alloc] initWithDisplayString:_NS("All genres")];
+            } else if (_currentParentType == VLC_ML_PARENT_ARTIST) {
+                group = [[VLCMediaLibraryAllItemsGroup alloc] initWithDisplayString:_NS("All artists")];
+            }
+
+            NSAssert(group != nil, @"All items group should not be nil");
+            [mutableCollectionCopy insertObject:group atIndex:0];
+            self.displayedCollection = mutableCollectionCopy;
+        }
+
         [self resetLayoutsForOperation:^{
             [self.collectionView reloadData];
             [self.gridModeListTableView reloadData];
-            [self.gridModeListSelectionCollectionView reloadData];
             [self.collectionSelectionTableView reloadData];
-            [self.groupSelectionTableView reloadData];
             [self.songsTableView reloadData];
         }];
         [self restoreSelectionState];
@@ -625,13 +616,7 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
         [self.songsTableView reloadDataForRowIndexes:rowIndexSet columnIndexes:songsTableColumnIndexSet];
 
         // Don't update gridModeListSelectionCollectionView, let its VLCLibraryAudioGroupDataSource do it.
-        // TODO: Stop splitting functionality for these audio source selection views between this data source
-        // TODO: and the VLCLibraryAudioGroupDataSource, it is super confusing
-
-        // Also don't update:
-        // - gridModeListTableView, as this will only show artists/genres
-        // - collectionSelectionTableView, as this will only show artists/genres/albums
-        // - groupSelectionTableView, as this shows cells for albums (and each cell has its own data source with media items)
+        // Also don't update collectionSelectionTableView, as this will only show artists/genres/albums
     }];
 }
 
@@ -666,28 +651,28 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
     _audioLibrarySegment = audioLibrarySegment;
     switch (_audioLibrarySegment) {
         case VLCAudioLibraryArtistsSegment:
-            self.displayedCollection = [self.libraryModel listOfArtists];
             _currentParentType = VLC_ML_PARENT_ARTIST;
             break;
         case VLCAudioLibraryAlbumsSegment:
-            self.displayedCollection = [self.libraryModel listOfAlbums];
             _currentParentType = VLC_ML_PARENT_ALBUM;
             break;
         case VLCAudioLibrarySongsSegment:
-            self.displayedCollection = [self.libraryModel listOfAudioMedia];
             _currentParentType = VLC_ML_PARENT_UNKNOWN;
             break;
         case VLCAudioLibraryGenresSegment:
-            self.displayedCollection = [self.libraryModel listOfGenres];
             _currentParentType = VLC_ML_PARENT_GENRE;
             break;
-
         default:
             NSAssert(1, @"reached the unreachable");
             break;
     }
 
-    _audioGroupDataSource.representedListOfAlbums = nil; // Clear whatever was being shown before
+    _audioGroupDataSource.representedAudioGroup = nil; // Clear whatever was being shown before
+
+    [_songsTableView deselectAll:self];
+    [_collectionSelectionTableView deselectAll:self];
+    [_collectionView deselectAll:self];
+
     [self reloadData];
 }
 
@@ -701,24 +686,14 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 
 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
 {
-    const NSInteger numItems = self.displayedCollection.count;
-    return [self displayAllArtistsGenresTableEntry] ? numItems + 1 : numItems;
+    return self.displayedCollection.count;
 }
 
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtRow:(NSInteger)row
                                        forTableView:(NSTableView *)tableView
 {
-    BOOL viewDisplayingAllItemsEntry = [self displayAllArtistsGenresTableEntry];
-    BOOL provideAllItemsEntry = viewDisplayingAllItemsEntry && row == 0;
-
-    if (provideAllItemsEntry && _currentParentType == VLC_ML_PARENT_GENRE) {
-        return [[VLCMediaLibraryDummyItem alloc] initWithDisplayString:_NS("All genres")
-                                                      withDetailString:@""];
-    } else if (provideAllItemsEntry && _currentParentType == VLC_ML_PARENT_ARTIST) {
-        return [[VLCMediaLibraryDummyItem alloc] initWithDisplayString:_NS("All artists")
-                                                      withDetailString:@""];
-    } else if (viewDisplayingAllItemsEntry) {
-        return self.displayedCollection[row - 1];
+    if (row < 0 || row >= self.displayedCollection.count) {
+        return nil;
     }
 
     return self.displayedCollection[row];
@@ -728,7 +703,7 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 {
     NSParameterAssert(tableView);
     
-    if (tableView != _collectionSelectionTableView && tableView != _groupSelectionTableView && tableView != _gridModeListTableView) {
+    if (tableView != _collectionSelectionTableView && tableView != _gridModeListTableView) {
         return;
     }
 
@@ -737,29 +712,15 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
     }
 
     const NSInteger selectedRow = tableView.selectedRow;
-    const BOOL showingAllItemsEntry = [self displayAllArtistsGenresTableEntry];
-    const NSInteger libraryItemIndex = showingAllItemsEntry ? selectedRow - 1 : selectedRow;
-
-    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
-        if (libraryItemIndex < 0 && showingAllItemsEntry) {
-            self->_audioGroupDataSource.representedListOfAlbums = self->_libraryModel.listOfAlbums;
-        } else {
-            id<VLCMediaLibraryItemProtocol> libraryItem = self.displayedCollection[libraryItemIndex];
-
-            if (self->_currentParentType == VLC_ML_PARENT_ALBUM) {
-                self->_audioGroupDataSource.representedListOfAlbums = @[(VLCMediaLibraryAlbum *)libraryItem];
-            } else if(self->_currentParentType != VLC_ML_PARENT_UNKNOWN) {
-                self->_audioGroupDataSource.representedListOfAlbums = [self->_libraryModel listAlbumsOfParentType:self->_currentParentType forID:libraryItem.libraryID];
-            } else { // FIXME: we have nothing to show here
-                self->_audioGroupDataSource.representedListOfAlbums = nil;
-            }
-        }
+    if (selectedRow >= self.displayedCollection.count) {
+        return;
+    }
 
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [self.groupSelectionTableView reloadData];
-            [self.gridModeListSelectionCollectionView reloadData];
-        });
-    });
+    if (_currentParentType == VLC_ML_PARENT_UNKNOWN || selectedRow < 0) {
+        _audioGroupDataSource.representedAudioGroup = nil;
+    } else {
+        _audioGroupDataSource.representedAudioGroup = self.displayedCollection[selectedRow];
+    }
 }
 
 - (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors
@@ -805,18 +766,17 @@ NSString * const VLCLibraryYearSortDescriptorKey = @"VLCLibraryYearSortDescripto
 
 #pragma mark - table view double click actions
 
-- (void)groubSelectionDoubleClickAction:(id)sender
+- (void)groupSelectionDoubleClickAction:(id)sender
 {
-    NSArray *listOfAlbums = _audioGroupDataSource.representedListOfAlbums;
-    NSUInteger albumCount = listOfAlbums.count;
-    NSInteger clickedRow = _groupSelectionTableView.clickedRow;
+    NSTableView * const tableView = (NSTableView *)sender;
+    NSParameterAssert(tableView != nil);
 
-    if (!listOfAlbums || albumCount == 0 || clickedRow > albumCount) {
-        return;
-    }
+    const NSInteger clickedRow = tableView.clickedRow;
+    id<VLCMediaLibraryItemProtocol> libraryItem = self.displayedCollection[clickedRow - 1];
 
-    NSArray * const tracks = [listOfAlbums[clickedRow] tracksAsMediaItems];
-    [VLCMain.sharedInstance.libraryController appendItemsToPlaylist:tracks playFirstItemImmediately:YES];
+    [libraryItem iterateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem* mediaItem) {
+        [VLCMain.sharedInstance.libraryController appendItemToPlaylist:mediaItem playImmediately:YES];
+    }];
 }
 
 - (void)collectionSelectionDoubleClickAction:(id)sender
@@ -901,7 +861,13 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtIndexPath:(NSIndexPath *)indexPath
                                         forCollectionView:(NSCollectionView *)collectionView
 {
-    return self.displayedCollection[indexPath.item];
+    const NSUInteger indexPathItem = indexPath.item;
+
+    if (indexPathItem < 0 || indexPathItem >= self.displayedCollection.count) {
+        return nil;
+    }
+
+    return self.displayedCollection[indexPathItem];
 }
 
 @end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.h
=====================================
@@ -28,12 +28,16 @@
 NS_ASSUME_NONNULL_BEGIN
 
 @class VLCLibraryModel;
- at class VLCLibraryAudioGroupDataSource;
 @class VLCMediaLibraryAlbum;
+ at protocol VLCMediaLibraryAudioGroupProtocol;
 
 @interface VLCLibraryAudioGroupDataSource : NSObject <VLCLibraryTableViewDataSource, VLCLibraryCollectionViewDataSource>
 
- at property (readwrite, atomic, retain, nullable) NSArray <VLCMediaLibraryAlbum *> *representedListOfAlbums;
+ at property (readwrite, nonatomic, retain, nullable) id<VLCMediaLibraryAudioGroupProtocol> representedAudioGroup;
+ at property (readwrite, atomic, retain) NSArray <NSTableView *> *tableViews;
+ at property (readwrite, atomic, retain) NSArray <NSCollectionView *> *collectionViews;
+
++ (void)setupCollectionView:(NSCollectionView *)collectionView;
 
 @end
 


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.m
=====================================
@@ -26,18 +26,73 @@
 
 #import "main/VLCMain.h"
 
+#import "library/VLCLibraryController.h"
 #import "library/VLCLibraryDataTypes.h"
 #import "library/VLCLibraryCollectionViewItem.h"
 #import "library/VLCLibraryCollectionViewFlowLayout.h"
+#import "library/VLCLibraryModel.h"
 #import "library/VLCLibraryWindow.h"
 
 #import "library/audio-library/VLCLibraryAlbumTableCellView.h"
+#import "library/audio-library/VLCLibraryAudioGroupHeaderView.h"
 #import "library/audio-library/VLCLibraryCollectionViewAlbumSupplementaryDetailView.h"
 
 #import "views/VLCSubScrollView.h"
 
+ at interface VLCLibraryAudioGroupDataSource ()
+
+ at property (readwrite, atomic, strong) NSArray<VLCMediaLibraryAlbum *> *representedListOfAlbums;
+
+ at end
+
 @implementation VLCLibraryAudioGroupDataSource
 
++ (void)setupCollectionView:(NSCollectionView *)collectionView
+{
+    NSNib * const audioGroupHeaderView = [[NSNib alloc] initWithNibNamed:@"VLCLibraryAudioGroupHeaderView"
+                                                                  bundle:nil];
+    [collectionView registerNib:audioGroupHeaderView
+     forSupplementaryViewOfKind:NSCollectionElementKindSectionHeader
+                 withIdentifier:VLCLibraryAudioGroupHeaderViewIdentifier];
+}
+
+- (void)reloadViews
+{
+    for (NSTableView * const tableView in _tableViews) {
+        [tableView reloadData];
+    }
+
+    for (NSCollectionView * const collectionView in _collectionViews) {
+        [collectionView reloadData];
+    }
+}
+
+- (void)updateRepresentedListOfAlbums
+{
+    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
+        VLCLibraryModel * const libraryModel = VLCMain.sharedInstance.libraryController.libraryModel;
+        if (self.representedAudioGroup == nil) {
+            self.representedListOfAlbums = libraryModel.listOfAlbums;
+        } else {
+            self.representedListOfAlbums = self.representedAudioGroup.albums;
+        }
+
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self reloadViews];
+        });
+    });
+}
+
+- (void)setRepresentedAudioGroup:(VLCAbstractMediaLibraryAudioGroup *)representedAudioGroup
+{
+    if (representedAudioGroup == _representedAudioGroup) {
+        return;
+    }
+
+    _representedAudioGroup = representedAudioGroup;
+    [self updateRepresentedListOfAlbums];
+}
+
 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
 {
     if (self.representedListOfAlbums != nil) {
@@ -50,6 +105,10 @@
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtRow:(NSInteger)row
                                        forTableView:(NSTableView *)tableView
 {
+    if (row < 0 || row >= self.representedListOfAlbums.count) {
+        return nil;
+    }
+
     return self.representedListOfAlbums[row];
 }
 
@@ -88,6 +147,10 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
 
         return albumSupplementaryDetailView;
 
+    } else if ([kind isEqualToString:NSCollectionElementKindSectionHeader]) {
+        VLCLibraryAudioGroupHeaderView * const headerView = [collectionView makeSupplementaryViewOfKind:kind withIdentifier:VLCLibraryAudioGroupHeaderViewIdentifier forIndexPath:indexPath];
+        headerView.representedItem = _representedAudioGroup;
+        return headerView;
     }
 
     return nil;
@@ -103,7 +166,13 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtIndexPath:(NSIndexPath *)indexPath
                                         forCollectionView:(NSCollectionView *)collectionView
 {
-    return self.representedListOfAlbums[indexPath.item];
+    const NSUInteger indexPathItem = indexPath.item;
+
+    if (indexPathItem < 0 || indexPathItem >= self.representedListOfAlbums.count) {
+        return nil;
+    }
+
+    return self.representedListOfAlbums[indexPathItem];
 }
 
 @end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.h
=====================================
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * VLCLibraryAudioGroupHeaderView.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <developer at claudiocambra.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+ at protocol VLCMediaLibraryAudioGroupProtocol;
+
+extern NSString * const VLCLibraryAudioGroupHeaderViewIdentifier;
+
+ at interface VLCLibraryAudioGroupHeaderView : NSView
+
+ at property (class, readonly) const CGSize defaultHeaderSize;
+
+ at property (readwrite, retain, nonatomic) id<VLCMediaLibraryAudioGroupProtocol> representedItem;
+
+ at property (readwrite, weak) IBOutlet NSTextField *titleTextField;
+ at property (readwrite, weak) IBOutlet NSTextField *detailTextField;
+ at property (readwrite, weak) IBOutlet NSButton *playButton;
+ at property (readwrite, weak) IBOutlet NSButton *queueButton;
+
+- (IBAction)play:(id)sender;
+- (IBAction)enqueue:(id)sender;
+
+ at end
+
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.m
=====================================
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * VLCLibraryAudioGroupHeaderView.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <developer at claudiocambra.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "VLCLibraryAudioGroupHeaderView.h"
+
+#import "extensions/NSColor+VLCAdditions.h"
+#import "main/VLCMain.h"
+#import "library/VLCLibraryController.h"
+#import "library/VLCLibraryDataTypes.h"
+
+NSString * const VLCLibraryAudioGroupHeaderViewIdentifier = @"VLCLibraryAudioGroupHeaderViewIdentifier";
+
+ at implementation VLCLibraryAudioGroupHeaderView
+
++ (CGSize)defaultHeaderSize
+{
+    return CGSizeMake(690., 86.);
+}
+
+- (void)awakeFromNib
+{
+    if (@available(macOS 10.14, *)) {
+        _playButton.bezelColor = NSColor.VLCAccentColor;
+    }
+}
+
+- (void)updateRepresentation
+{
+    if (_representedItem == nil) {
+        _titleTextField.stringValue = @"Unknown";
+        _detailTextField.stringValue = @"Unknown";
+        return;
+    }
+
+    _titleTextField.stringValue = _representedItem.displayString;
+    _detailTextField.stringValue = _representedItem.detailString;
+}
+
+- (void)setRepresentedItem:(id<VLCMediaLibraryAudioGroupProtocol>)representedItem
+{
+    if (representedItem == _representedItem) {
+        return;
+    }
+
+    _representedItem = representedItem;
+    [self updateRepresentation];
+}
+
+- (IBAction)play:(id)sender
+{
+    VLCLibraryController * const libraryController = VLCMain.sharedInstance.libraryController;
+
+    // We want to add all the tracks to the playlist but only play the first one immediately,
+    // otherwise we will skip straight to the last track of the last album from the artist
+    __block BOOL playImmediately = YES;
+    [_representedItem iterateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem* mediaItem) {
+        [libraryController appendItemToPlaylist:mediaItem playImmediately:playImmediately];
+
+        if(playImmediately) {
+            playImmediately = NO;
+        }
+    }];
+}
+
+- (IBAction)enqueue:(id)sender
+{
+    VLCLibraryController * const libraryController = VLCMain.sharedInstance.libraryController;
+
+    [_representedItem iterateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem* mediaItem) {
+        [libraryController appendItemToPlaylist:mediaItem playImmediately:NO];
+    }];
+}
+
+ at end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
=====================================
@@ -36,6 +36,7 @@
 #import "library/audio-library/VLCLibraryAlbumTableCellView.h"
 #import "library/audio-library/VLCLibraryAudioDataSource.h"
 #import "library/audio-library/VLCLibraryAudioGroupDataSource.h"
+#import "library/audio-library/VLCLibraryAudioGroupHeaderView.h"
 #import "library/audio-library/VLCLibraryAudioGroupTableViewDelegate.h"
 #import "library/audio-library/VLCLibraryAudioTableViewDelegate.h"
 
@@ -133,14 +134,14 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = @"VLCLibraryPlaceholderAudi
     _audioDataSource = [[VLCLibraryAudioDataSource alloc] init];
     _audioDataSource.libraryModel = VLCMain.sharedInstance.libraryController.libraryModel;
     _audioDataSource.collectionSelectionTableView = _audioCollectionSelectionTableView;
-    _audioDataSource.groupSelectionTableView = _audioGroupSelectionTableView;
     _audioDataSource.songsTableView = _audioSongTableView;
     _audioDataSource.collectionView = _audioLibraryCollectionView;
     _audioDataSource.gridModeListTableView = _audioLibraryGridModeSplitViewListTableView;
-    _audioDataSource.gridModeListSelectionCollectionView = _audioLibraryGridModeSplitViewListSelectionCollectionView;
     [_audioDataSource setup];
 
     _audioGroupDataSource = [[VLCLibraryAudioGroupDataSource alloc] init];
+    _audioGroupDataSource.tableViews = @[_audioGroupSelectionTableView];
+    _audioGroupDataSource.collectionViews = @[_audioLibraryGridModeSplitViewListSelectionCollectionView];
     _audioDataSource.audioGroupDataSource = _audioGroupDataSource;
 }
 
@@ -203,7 +204,14 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = @"VLCLibraryPlaceholderAudi
     audioLibraryGridModeListSelectionCollectionViewLayout.minimumLineSpacing = collectionItemSpacing;
     audioLibraryGridModeListSelectionCollectionViewLayout.minimumInteritemSpacing = collectionItemSpacing;
     audioLibraryGridModeListSelectionCollectionViewLayout.sectionInset = collectionViewSectionInset;
+    audioLibraryGridModeListSelectionCollectionViewLayout.headerReferenceSize = VLCLibraryAudioGroupHeaderView.defaultHeaderSize;
 
+    if (@available(macOS 10.12, *)) {
+        audioLibraryGridModeListSelectionCollectionViewLayout.sectionHeadersPinToVisibleBounds = YES;
+    }
+
+    [VLCLibraryAudioDataSource setupCollectionView:_audioLibraryGridModeSplitViewListSelectionCollectionView];
+    [VLCLibraryAudioGroupDataSource setupCollectionView:_audioLibraryGridModeSplitViewListSelectionCollectionView];
 }
 
 - (void)setupAudioPlaceholderView


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.m
=====================================
@@ -46,6 +46,8 @@ NSCollectionViewSupplementaryElementKind const VLCLibraryCollectionViewAudioGrou
 - (void)awakeFromNib
 {
     _audioGroupAlbumsDataSource = [[VLCLibraryAudioGroupDataSource alloc] init];
+    _audioGroupAlbumsDataSource.tableViews = @[_audioGroupAlbumsTableView];
+    
     _audioGroupAlbumsTableViewDelegate = [[VLCLibraryAudioGroupTableViewDelegate alloc] init];
 
     _audioGroupAlbumsTableView.dataSource = _audioGroupAlbumsDataSource;
@@ -97,14 +99,7 @@ NSCollectionViewSupplementaryElementKind const VLCLibraryCollectionViewAudioGrou
     }
 
     _audioGroupNameTextField.stringValue = _representedAudioGroup.displayString;
-
-    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
-        self->_audioGroupAlbumsDataSource.representedListOfAlbums = self->_representedAudioGroup.albums;
-
-        dispatch_async(dispatch_get_main_queue(), ^{
-            [self->_audioGroupAlbumsTableView reloadData];
-        });
-    });
+    _audioGroupAlbumsDataSource.representedAudioGroup = _representedAudioGroup;
 }
 
 @end


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewContainerViewDataSource.m
=====================================
@@ -297,6 +297,12 @@ viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
 - (id<VLCMediaLibraryItemProtocol>)libraryItemAtIndexPath:(NSIndexPath *)indexPath
                                         forCollectionView:(NSCollectionView *)collectionView
 {
+    const NSUInteger indexPathItem = indexPath.item;
+
+    if (indexPathItem < 0 || indexPathItem >= self.collectionArray.count) {
+        return nil;
+    }
+
     return self.collectionArray[indexPath.item];
 }
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9e798e2473238b47841c5ee4eb86807d0ed8e142...3917282dae74900d549b7507d8365ee8023aa2c1

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9e798e2473238b47841c5ee4eb86807d0ed8e142...3917282dae74900d549b7507d8365ee8023aa2c1
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list