[vlc-commits] [Git][videolan/vlc][master] macosx: Play genre's songs correctly from the collection view

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Mon Jul 11 07:05:48 UTC 2022



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
c38bfea9 by Claudio Cambra at 2022-07-11T06:44:02+00:00
macosx: Play genre's songs correctly from the collection view

Signed-off-by: Claudio Cambra <claudio.cambra at gmail.com>

- - - - -


9 changed files:

- modules/gui/macosx/Makefile.am
- + modules/gui/macosx/UI/VLCLibraryCollectionViewGenreItem.xib
- modules/gui/macosx/library/VLCLibraryAudioDataSource.m
- + modules/gui/macosx/library/VLCLibraryCollectionViewGenreItem.h
- + modules/gui/macosx/library/VLCLibraryCollectionViewGenreItem.m
- modules/gui/macosx/library/VLCLibraryDataTypes.h
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/VLCLibraryMenuController.h
- modules/gui/macosx/library/VLCLibraryMenuController.m


Changes:

=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -64,6 +64,8 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/library/VLCLibraryCollectionViewAlbumItem.m \
 	gui/macosx/library/VLCLibraryCollectionViewArtistItem.h \
 	gui/macosx/library/VLCLibraryCollectionViewArtistItem.m \
+	gui/macosx/library/VLCLibraryCollectionViewGenreItem.h \
+	gui/macosx/library/VLCLibraryCollectionViewGenreItem.m \
 	gui/macosx/library/VLCLibraryCollectionViewItemProtocol.h \
 	gui/macosx/library/VLCLibraryCollectionViewSupplementaryElementView.h \
 	gui/macosx/library/VLCLibraryCollectionViewSupplementaryElementView.m \
@@ -302,6 +304,7 @@ libmacosx_plugin_la_XIB_SOURCES = \
 	gui/macosx/UI/VLCLibraryCollectionViewItem.xib \
 	gui/macosx/UI/VLCLibraryCollectionViewAlbumItem.xib \
 	gui/macosx/UI/VLCLibraryCollectionViewArtistItem.xib \
+	gui/macosx/UI/VLCLibraryCollectionViewGenreItem.xib \
 	gui/macosx/UI/VLCMediaSourceCollectionViewItem.xib \
 	gui/macosx/UI/VLCMediaSourceDeviceCollectionViewItem.xib \
 	gui/macosx/UI/VLCInformationWindow.xib \


=====================================
modules/gui/macosx/UI/VLCLibraryCollectionViewGenreItem.xib
=====================================
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="VLCLibraryCollectionViewAlbumItem">
+            <connections>
+                <outlet property="addToPlaylistButton" destination="Ubz-8I-W2F" id="k0q-b1-PZi"/>
+                <outlet property="annotationTextField" destination="tm2-NW-WsZ" id="Miy-RS-Rol"/>
+                <outlet property="durationTextField" destination="VAn-gF-QiZ" id="U8T-Cs-HaL"/>
+                <outlet property="mediaImageView" destination="2aB-sB-hfY" id="Sv0-G1-KNm"/>
+                <outlet property="mediaTitleTextField" destination="OBS-Eh-1mT" id="h1n-PU-IAx"/>
+                <outlet property="playInstantlyButton" destination="S3I-5Z-qgS" id="JlC-bE-i5Y"/>
+                <outlet property="progressIndicator" destination="dFt-oZ-h9P" id="JC6-gk-Mid"/>
+                <outlet property="unplayedIndicatorTextField" destination="u2r-zy-XEW" id="56s-K4-Kxr"/>
+                <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="Hz6-mo-xeY" customClass="VLCTrackingView">
+            <rect key="frame" x="0.0" y="0.0" width="256" height="214"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="2aB-sB-hfY" customClass="VLCImageView">
+                    <rect key="frame" x="0.0" y="49" width="256" height="165"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="dFt-oZ-h9P" customClass="VLCLinearProgressIndicator">
+                            <rect key="frame" x="0.0" y="0.0" width="256" height="4"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="4" id="lyQ-kl-gVk"/>
+                            </constraints>
+                        </customView>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="S3I-5Z-qgS">
+                            <rect key="frame" x="96" y="51" width="64" height="64"/>
+                            <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="libraryPlay" imagePosition="only" alignment="center" inset="2" id="IHP-p1-d0R">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <connections>
+                                <action selector="playInstantly:" target="-2" id="E2B-oj-rx3"/>
+                            </connections>
+                        </button>
+                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tm2-NW-WsZ" customClass="VLCRoundedCornerTextField">
+                            <rect key="frame" x="8" y="141" width="37" height="17"/>
+                            <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="tyb-Ur-7J9">
+                                <font key="font" metaFont="system"/>
+                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                    </subviews>
+                    <constraints>
+                        <constraint firstAttribute="bottom" secondItem="dFt-oZ-h9P" secondAttribute="bottom" id="4q3-3S-7PA"/>
+                        <constraint firstItem="S3I-5Z-qgS" firstAttribute="centerX" secondItem="2aB-sB-hfY" secondAttribute="centerX" id="Seo-tS-piW"/>
+                        <constraint firstItem="S3I-5Z-qgS" firstAttribute="centerY" secondItem="2aB-sB-hfY" secondAttribute="centerY" id="ZWU-oW-OVa"/>
+                        <constraint firstItem="dFt-oZ-h9P" firstAttribute="leading" secondItem="2aB-sB-hfY" secondAttribute="leading" id="gTe-sx-hdP"/>
+                        <constraint firstAttribute="trailing" secondItem="dFt-oZ-h9P" secondAttribute="trailing" id="kBI-UU-vnc"/>
+                    </constraints>
+                </customView>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OBS-Eh-1mT">
+                    <rect key="frame" x="-2" y="21" width="52" height="24"/>
+                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" title="Label" usesSingleLineMode="YES" id="7Hy-o3-LvX">
+                        <font key="font" size="20" name=".AppleSystemUIFont"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="u2r-zy-XEW">
+                    <rect key="frame" x="224" y="1" width="34" height="17"/>
+                    <textFieldCell key="cell" lineBreakMode="clipping" title="NEW" id="NeT-5U-eZn">
+                        <font key="font" metaFont="system"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+                <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ubz-8I-W2F">
+                    <rect key="frame" x="222" y="187" width="20" height="20"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="20" id="XhX-7U-Nxj"/>
+                        <constraint firstAttribute="height" constant="20" id="ZDT-YM-Cbr"/>
+                    </constraints>
+                    <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ellipsis" imagePosition="only" alignment="center" inset="2" id="6ko-MM-ds0">
+                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                        <font key="font" metaFont="system"/>
+                    </buttonCell>
+                    <connections>
+                        <action selector="addToPlaylist:" target="-2" id="2C9-Rn-VAb"/>
+                    </connections>
+                </button>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VAn-gF-QiZ">
+                    <rect key="frame" x="-2" y="0.0" width="42" height="19"/>
+                    <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="LSS-jh-llZ">
+                        <font key="font" size="15" name=".AppleSystemUIFont"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+            </subviews>
+            <constraints>
+                <constraint firstItem="2aB-sB-hfY" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="3Ah-0T-rA9"/>
+                <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="OBS-Eh-1mT" secondAttribute="trailing" id="457-oy-EbD"/>
+                <constraint firstItem="Ubz-8I-W2F" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="7" id="8Qf-Un-Gdl"/>
+                <constraint firstItem="VAn-gF-QiZ" firstAttribute="top" secondItem="OBS-Eh-1mT" secondAttribute="bottom" constant="2" id="ALi-0z-Mza"/>
+                <constraint firstAttribute="trailing" secondItem="u2r-zy-XEW" secondAttribute="trailing" id="Dd7-va-0UJ"/>
+                <constraint firstItem="u2r-zy-XEW" firstAttribute="centerY" secondItem="VAn-gF-QiZ" secondAttribute="centerY" id="H5N-j9-THf"/>
+                <constraint firstAttribute="bottom" secondItem="VAn-gF-QiZ" secondAttribute="bottom" id="Kp0-Hx-3Ek"/>
+                <constraint firstItem="VAn-gF-QiZ" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="QUW-dn-Fbc"/>
+                <constraint firstAttribute="trailing" secondItem="Ubz-8I-W2F" secondAttribute="trailing" constant="14" id="ZVz-SL-rxZ"/>
+                <constraint firstItem="tm2-NW-WsZ" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="7" id="cvk-A5-enS"/>
+                <constraint firstItem="tm2-NW-WsZ" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="10" id="fH0-Om-7gV"/>
+                <constraint firstAttribute="trailing" secondItem="2aB-sB-hfY" secondAttribute="trailing" id="oZw-Ab-83p"/>
+                <constraint firstItem="2aB-sB-hfY" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="t9g-tX-AQX"/>
+                <constraint firstItem="OBS-Eh-1mT" firstAttribute="top" secondItem="2aB-sB-hfY" secondAttribute="bottom" constant="4" id="vJy-Kf-4Jh"/>
+                <constraint firstItem="OBS-Eh-1mT" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="yvp-xr-geN"/>
+            </constraints>
+        </customView>
+    </objects>
+    <resources>
+        <image name="ellipsis" width="17" height="3"/>
+        <image name="libraryPlay" width="64" height="64"/>
+    </resources>
+</document>


=====================================
modules/gui/macosx/library/VLCLibraryAudioDataSource.m
=====================================
@@ -32,6 +32,7 @@
 #import "library/VLCLibraryCollectionViewItem.h"
 #import "library/VLCLibraryCollectionViewAlbumItem.h"
 #import "library/VLCLibraryCollectionViewArtistItem.h"
+#import "library/VLCLibraryCollectionViewGenreItem.h"
 
 #import "extensions/NSString+Helpers.h"
 #import "views/VLCImageView.h"
@@ -71,6 +72,7 @@ static NSString *VLCAudioLibraryCellIdentifier = @"VLCAudioLibraryCellIdentifier
     [_collectionView registerClass:[VLCLibraryCollectionViewItem class] forItemWithIdentifier:VLCLibraryCellIdentifier];
     [_collectionView registerClass:[VLCLibraryCollectionViewAlbumItem class] forItemWithIdentifier:VLCLibraryAlbumCellIdentifier];
     [_collectionView registerClass:[VLCLibraryCollectionViewArtistItem class] forItemWithIdentifier:VLCLibraryArtistCellIdentifier];
+    [_collectionView registerClass:[VLCLibraryCollectionViewGenreItem class] forItemWithIdentifier:VLCLibraryGenreCellIdentifier];
     
     NSCollectionViewFlowLayout *flowLayout = _collectionView.collectionViewLayout;
     flowLayout.itemSize = CGSizeMake(214., 260.);
@@ -411,22 +413,17 @@ static NSString *VLCAudioLibraryCellIdentifier = @"VLCAudioLibraryCellIdentifier
         }
         case VLC_ML_PARENT_UNKNOWN:
         {
+            // This is the only one that uses the default VLCLibraryCollectionViewItem
             VLCMediaLibraryMediaItem *mediaItem = _displayedCollection[indexPath.item];
             viewItem.representedMediaItem = mediaItem;
             break;
         }
         case VLC_ML_PARENT_GENRE:
         {
-            // TODO: Have genre-specific view item
+            VLCLibraryCollectionViewGenreItem *viewGenreItem = [collectionView makeItemWithIdentifier:VLCLibraryGenreCellIdentifier forIndexPath:indexPath];
             VLCMediaLibraryGenre *genre = _displayedCollection[indexPath.item];
-            viewItem.mediaTitleTextField.stringValue = genre.name;
-            if (genre.numberOfTracks > 1) {
-                viewItem.durationTextField.stringValue = [NSString stringWithFormat:_NS("%u songs"), genre.numberOfTracks];
-            } else {
-                viewItem.durationTextField.stringValue = _NS("1 song");
-            }
-            viewItem.mediaImageView.image = [NSImage imageNamed: @"noart.png"];
-            break;
+            viewGenreItem.representedGenre = genre;
+            return viewGenreItem;
         }
         default:
             break;


=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewGenreItem.h
=====================================
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * VLCLibraryCollectionViewGenreItem.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <claudio.cambra at gmail.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>
+#import "VLCLibraryCollectionViewItemProtocol.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+ at class VLCMediaLibraryGenre;
+
+extern NSString *VLCLibraryGenreCellIdentifier;
+
+ at interface VLCLibraryCollectionViewGenreItem : NSCollectionViewItem<VLCLibraryCollectionViewItemProtocol>
+
+ at property (readwrite, retain, nonatomic) VLCMediaLibraryGenre *representedGenre;
+
+ at end
+
+NS_ASSUME_NONNULL_END
+


=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewGenreItem.m
=====================================
@@ -0,0 +1,244 @@
+/*****************************************************************************
+ * VLCLibraryCollectionViewGenreItem.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <claudio.cambra at gmail.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 "VLCLibraryCollectionViewGenreItem.h"
+
+#import "main/VLCMain.h"
+#import "library/VLCLibraryController.h"
+#import "library/VLCLibraryDataTypes.h"
+#import "library/VLCLibraryModel.h"
+#import "library/VLCLibraryMenuController.h"
+#import "views/VLCImageView.h"
+#import "views/VLCLinearProgressIndicator.h"
+#import "views/VLCTrackingView.h"
+#import "extensions/NSString+Helpers.h"
+#import "extensions/NSFont+VLCAdditions.h"
+#import "extensions/NSColor+VLCAdditions.h"
+#import "extensions/NSView+VLCAdditions.h"
+
+NSString *VLCLibraryGenreCellIdentifier = @"VLCLibraryGenreCellIdentifier";
+
+ at interface VLCLibraryCollectionViewGenreItem()
+{
+    VLCLibraryController *_libraryController;
+    VLCLibraryMenuController *_menuController;
+}
+ at end
+
+ at implementation VLCLibraryCollectionViewGenreItem
+
+ at synthesize mediaTitleTextField = _mediaTitleTextField;
+ at synthesize annotationTextField = _annotationTextField;
+ at synthesize unplayedIndicatorTextField = _unplayedIndicatorTextField;
+ at synthesize durationTextField = _durationTextField;
+ at synthesize mediaImageView = _mediaImageView;
+ at synthesize playInstantlyButton = _playInstantlyButton;
+ at synthesize addToPlaylistButton = _addToPlaylistButton;
+ at synthesize progressIndicator = _progressIndicator;
+
+- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+        // TODO: Update genre on a VLCLibraryModelGenreUpdated signal
+        [notificationCenter addObserver:self
+                               selector:@selector(updateFontBasedOnSetting:)
+                                   name:VLCConfigurationChangedNotification
+                                 object:nil];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    if (@available(macOS 10.14, *)) {
+        [[NSApplication sharedApplication] removeObserver:self forKeyPath:@"effectiveAppearance"];
+    }
+}
+
+- (void)awakeFromNib
+{
+    [(VLCTrackingView *)self.view setViewToHide:self.playInstantlyButton];
+    self.durationTextField.textColor = [NSColor VLClibrarySubtitleColor];
+    self.annotationTextField.font = [NSFont VLClibraryCellAnnotationFont];
+    self.annotationTextField.textColor = [NSColor VLClibraryAnnotationColor];
+    self.annotationTextField.backgroundColor = [NSColor VLClibraryAnnotationBackgroundColor];
+    self.unplayedIndicatorTextField.stringValue = _NS("NEW");
+    self.unplayedIndicatorTextField.font = [NSFont VLClibraryHighlightCellHighlightLabelFont];
+    self.unplayedIndicatorTextField.textColor = [NSColor VLClibraryHighlightColor];
+
+    if (@available(macOS 10.14, *)) {
+        [[NSApplication sharedApplication] addObserver:self
+                                            forKeyPath:@"effectiveAppearance"
+                                               options:0
+                                               context:nil];
+    }
+
+    [self updateColoredAppearance];
+    [self updateFontBasedOnSetting:nil];
+    [self prepareForReuse];
+}
+
+#pragma mark - dynamic appearance
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
+                       context:(void *)context
+{
+    [self updateColoredAppearance];
+}
+
+- (void)updateColoredAppearance
+{
+    self.mediaTitleTextField.textColor = self.view.shouldShowDarkAppearance ? [NSColor VLClibraryDarkTitleColor] : [NSColor VLClibraryLightTitleColor];
+}
+
+- (void)updateFontBasedOnSetting:(NSNotification *)aNotification
+{
+    if (config_GetInt("macosx-large-text")) {
+        self.mediaTitleTextField.font = [NSFont VLClibraryLargeCellTitleFont];
+        self.durationTextField.font = [NSFont VLClibraryLargeCellSubtitleFont];
+    } else {
+        self.mediaTitleTextField.font = [NSFont VLClibrarySmallCellTitleFont];
+        self.durationTextField.font = [NSFont VLClibrarySmallCellSubtitleFont];
+    }
+}
+
+#pragma mark - view representation
+
+- (void)prepareForReuse
+{
+    [super prepareForReuse];
+    _playInstantlyButton.hidden = YES;
+    _mediaTitleTextField.stringValue = @"";
+    _durationTextField.stringValue = [NSString stringWithTime:0];
+    _mediaImageView.image = nil;
+    _annotationTextField.hidden = YES;
+    _progressIndicator.hidden = YES;
+    _unplayedIndicatorTextField.hidden = YES;
+}
+
+- (void)setRepresentedGenre:(VLCMediaLibraryGenre *)representedGenre
+{
+    if (!_libraryController) {
+        _libraryController = [[VLCMain sharedInstance] libraryController];
+    }
+
+    _representedGenre = representedGenre;
+    [self updateRepresentation];
+}
+
+- (void)genreUpdated:(NSNotification *)aNotification
+{
+    VLCMediaLibraryGenre *updatedGenre = aNotification.object;
+    if (updatedGenre == nil || _representedGenre == nil) {
+        return;
+    }
+    if (updatedGenre.genreID == _representedGenre.genreID) {
+        [self updateRepresentation];
+    }
+}
+
+- (void)updateRepresentation
+{
+    if (_representedGenre == nil) {
+        NSAssert(1, @"no genre assigned for collection view item", nil);
+        return;
+    }
+
+    _mediaTitleTextField.stringValue = _representedGenre.name;
+
+    if (_representedGenre.numberOfTracks > 1) {
+        _durationTextField.stringValue = [NSString stringWithFormat:_NS("%u songs"), _representedGenre.numberOfTracks];
+    } else {
+        _durationTextField.stringValue = _NS("1 song");
+    }
+
+    _mediaImageView.image = [self imageForMedia];
+
+    // TODO: Show artist tracks progress with progress indicator
+}
+
+- (NSImage *)imageForMedia
+{
+    return [NSImage imageNamed: @"noart.png"];
+}
+
+#pragma mark - actions
+
+- (IBAction)playInstantly:(id)sender
+{
+    if (!_libraryController) {
+        _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 genre
+    __block BOOL playImmediately = YES;
+    [_representedGenre iterateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem* mediaItem) {
+        [_libraryController appendItemToPlaylist:mediaItem playImmediately:playImmediately];
+
+        if(playImmediately) {
+            playImmediately = NO;
+        }
+    }];
+}
+
+- (IBAction)addToPlaylist:(id)sender
+{
+    if (!_libraryController) {
+        _libraryController = [[VLCMain sharedInstance] libraryController];
+    }
+
+    [_representedGenre iterateMediaItemsWithBlock:^(VLCMediaLibraryMediaItem* mediaItem) {
+        [_libraryController appendItemToPlaylist:mediaItem playImmediately:NO];
+    }];
+}
+
+-(void)mouseDown:(NSEvent *)theEvent
+{
+    if (theEvent.modifierFlags & NSControlKeyMask) {
+        if (!_menuController) {
+            _menuController = [[VLCLibraryMenuController alloc] init];
+        }
+        [_menuController setRepresentedGenre:self.representedGenre];
+        [_menuController popupMenuWithEvent:theEvent forView:self.view];
+    }
+
+    [super mouseDown:theEvent];
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent
+{
+    if (!_menuController) {
+        _menuController = [[VLCLibraryMenuController alloc] init];
+    }
+    [_menuController setRepresentedGenre:self.representedGenre];
+    [_menuController popupMenuWithEvent:theEvent forView:self.view];
+
+    [super rightMouseDown:theEvent];
+}
+
+ at end


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.h
=====================================
@@ -137,6 +137,12 @@ extern const long long int VLCMediaLibraryMediaItemDurationDenominator;
 @property (readonly) int64_t genreID;
 @property (readonly) NSString *name;
 @property (readonly) size_t numberOfTracks;
+ at property (readonly) NSArray <VLCMediaLibraryArtist *> *artists;
+ at property (readonly) NSArray <VLCMediaLibraryAlbum *> *albums;
+ at property (readonly) NSArray <VLCMediaLibraryMediaItem *> *tracksAsMediaItems;
+
+- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock orderedBy:(int)mediaItemParentType;
+- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock;
 
 @end
 


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -240,7 +240,6 @@ NSString *VLCMediaLibraryMediaItemLibraryID = @"VLCMediaLibraryMediaItemLibraryI
     }
 }
 
-
 @end
 
 @implementation VLCMediaLibraryAlbum
@@ -304,6 +303,100 @@ NSString *VLCMediaLibraryMediaItemLibraryID = @"VLCMediaLibraryMediaItemLibraryI
     return self;
 }
 
+- (NSArray<VLCMediaLibraryAlbum *> *)albums
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf) {
+        return @[];
+    }
+    vlc_medialibrary_t *p_mediaLibrary = vlc_ml_instance_get(p_intf);
+    if (!p_mediaLibrary) {
+        return @[];
+    }
+    vlc_ml_album_list_t *p_albumList = vlc_ml_list_genre_albums(p_mediaLibrary, NULL, _genreID);
+    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:p_albumList->i_nb_items];
+    for (size_t x = 0; x < p_albumList->i_nb_items; x++) {
+        VLCMediaLibraryAlbum *album = [[VLCMediaLibraryAlbum alloc] initWithAlbum:&p_albumList->p_items[x]];
+        [mutableArray addObject:album];
+    }
+    vlc_ml_album_list_release(p_albumList);
+    return [mutableArray copy];
+}
+
+- (NSArray<VLCMediaLibraryAlbum *> *)artists
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf) {
+        return @[];
+    }
+    vlc_medialibrary_t *p_mediaLibrary = vlc_ml_instance_get(p_intf);
+    if (!p_mediaLibrary) {
+        return @[];
+    }
+    vlc_ml_artist_list_t *p_artistList = vlc_ml_list_genre_artists(p_mediaLibrary, NULL, _genreID);
+    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:p_artistList->i_nb_items];
+    for (size_t x = 0; x < p_artistList->i_nb_items; x++) {
+        VLCMediaLibraryArtist *artist = [[VLCMediaLibraryArtist alloc] initWithArtist:&p_artistList->p_items[x]];
+        [mutableArray addObject:artist];
+    }
+    vlc_ml_artist_list_release(p_artistList);
+    return [mutableArray copy];
+}
+
+- (NSArray<VLCMediaLibraryMediaItem *> *)tracksAsMediaItems
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf) {
+        return @[];
+    }
+    vlc_medialibrary_t *p_mediaLibrary = vlc_ml_instance_get(p_intf);
+    if (!p_mediaLibrary) {
+        return @[];
+    }
+    vlc_ml_media_list_t *p_mediaList = vlc_ml_list_genre_tracks(p_mediaLibrary, NULL, _genreID);
+    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithCapacity:p_mediaList->i_nb_items];
+    for (size_t x = 0; x < p_mediaList->i_nb_items; x++) {
+        VLCMediaLibraryMediaItem *mediaItem = [[VLCMediaLibraryMediaItem alloc] initWithMediaItem:&p_mediaList->p_items[x]];
+        [mutableArray addObject:mediaItem];
+    }
+    vlc_ml_media_list_release(p_mediaList);
+    return [mutableArray copy];
+}
+
+- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock
+{
+    // By default iterate album-by-album
+    [self iterateMediaItemsWithBlock:mediaItemBlock orderedBy:VLC_ML_PARENT_ALBUM];
+}
+
+- (void)iterateMediaItemsWithBlock:(void (^)(VLCMediaLibraryMediaItem*))mediaItemBlock orderedBy:(int)mediaItemParentType
+{
+    switch(mediaItemParentType) {
+        case VLC_ML_PARENT_ARTIST:
+        {
+            for(VLCMediaLibraryArtist *artist in self.artists) {
+                [artist iterateMediaItemsWithBlock:mediaItemBlock];
+            }
+            break;
+        }
+        case VLC_ML_PARENT_ALBUM:
+        {
+            for(VLCMediaLibraryAlbum *album in self.albums) {
+                [album iterateMediaItemsWithBlock:mediaItemBlock];
+            }
+            break;
+        }
+        case VLC_ML_PARENT_UNKNOWN:
+        default:
+        {
+            for(VLCMediaLibraryMediaItem *mediaItem in self.tracksAsMediaItems) {
+                mediaItemBlock(mediaItem);
+            }
+            break;
+        }
+    }
+}
+
 @end
 
 @interface VLCMediaLibraryMediaItem ()


=====================================
modules/gui/macosx/library/VLCLibraryMenuController.h
=====================================
@@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
 @class VLCMediaLibraryMediaItem;
 @class VLCMediaLibraryAlbum;
 @class VLCMediaLibraryArtist;
+ at class VLCMediaLibraryGenre;
 
 @interface VLCLibraryMenuController : NSObject
 
@@ -34,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)setRepresentedMediaItem:(VLCMediaLibraryMediaItem *)mediaItem;
 - (void)setRepresentedAlbum:(VLCMediaLibraryAlbum *)album;
 - (void)setRepresentedArtist:(VLCMediaLibraryArtist *)artist;
+- (void)setRepresentedGenre:(VLCMediaLibraryGenre *)genre;
 
 @end
 


=====================================
modules/gui/macosx/library/VLCLibraryMenuController.m
=====================================
@@ -38,6 +38,7 @@
     VLCMediaLibraryMediaItem *_representedMediaItem;
     VLCMediaLibraryAlbum *_representedAlbum;
     VLCMediaLibraryArtist *_representedArtist;
+    VLCMediaLibraryGenre *_representedGenre;
 }
 @end
 
@@ -92,6 +93,10 @@
     };
 
     switch(_currentRepresentedType) {
+        case VLC_ML_PARENT_GENRE:
+        {
+            [_representedGenre iterateMediaItemsWithBlock:mediaItemPlaylistHandler];
+        }
         case VLC_ML_PARENT_ARTIST:
         {
             [_representedArtist iterateMediaItemsWithBlock:mediaItemPlaylistHandler];
@@ -173,6 +178,10 @@
     };
 
     switch(_currentRepresentedType) {
+        case VLC_ML_PARENT_GENRE:
+        {
+            [_representedGenre iterateMediaItemsWithBlock:mediaItemTrashHandler];
+        }
         case VLC_ML_PARENT_ARTIST:
         {
             [_representedArtist iterateMediaItemsWithBlock:mediaItemTrashHandler];
@@ -212,6 +221,7 @@
     _representedMediaItem = nil;
     _representedAlbum = nil;
     _representedArtist = nil;
+    _representedGenre = nil;
     _currentRepresentedType = VLC_ML_PARENT_UNKNOWN;
 }
 
@@ -236,4 +246,11 @@
     _currentRepresentedType = VLC_ML_PARENT_ARTIST;
 }
 
+- (void)setRepresentedGenre:(VLCMediaLibraryGenre *)genre
+{
+    [self clearRepresentedMedia];
+    _representedGenre = genre;
+    _currentRepresentedType = VLC_ML_PARENT_GENRE;
+}
+
 @end



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/c38bfea9845d84acdc47963d3f2e1422eec0c7bf

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/c38bfea9845d84acdc47963d3f2e1422eec0c7bf
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