[vlc-commits] [Git][videolan/vlc][master] 27 commits: macosx: Add VLCPlaybackEndView
François Cartegnie (@fcartegnie)
gitlab at videolan.org
Tue May 20 07:06:24 UTC 2025
François Cartegnie pushed to branch master at VideoLAN / VLC
Commits:
5546068d by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Add VLCPlaybackEndView
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
b9001b49 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Add VLCPlaybackEndViewController
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
16743f07 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Connect playback end view to playback end view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
64ce69a8 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Set up text for playback end view for translation
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
723efb15 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Add countdown mechanism to playback end view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
a8bb5bb0 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Override init in playback end view controller to use expected nib
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
49babb62 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Emit timeout notification in playback end view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
937552d9 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Add method to display playback end view in main video view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
b700ae0f by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Emit notification on playback end view timeout via main video view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
07afd043 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Wait for playback end view timeout before disabling video appearance in library window
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
30989a55 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Match displaying of library-related controls and labels in playback end view with its parent main video view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
dcb49d7f by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Use existing returnToLibrary method within video view controller for playback end timeout
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
ef116086 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Emit relevant notifications on button interaction in playback end view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
6e383808 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Handle return to library notification in main video view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
ef8ef50a by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Invalidate the ongoing timer when interacting with the playback end view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
dc80a193 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: React to return to library button from playback end view in main video view controller
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
e3703a67 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Improve background for playback end view
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
3f4cc531 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Make playback end view inert in cases where user returns to library via other means than end view button
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
ae8b0485 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Ensure playback end view fits within video view bounds
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
a195362b by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Add convenience method to NSArray extension to get index of an ml item in an ml array
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
add38d76 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Add convenience creator method for VLCInputItem from NSURL
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
fc20e5e3 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Handle playqueue operation within playback end view
Limit playback end view controller to requesting view hide
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
f11f49a1 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Suggest playing next input item in folder in playback end view
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
cafe77c7 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Improve sizing and text layout in playback end view XIB
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
6bc98434 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Try to find relevant next media library item when current item is a media library media item in playback end view
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
ada32a3d by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Make end of playback view disable-able with setting
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
b65d5ca6 by Claudio Cambra at 2025-05-20T06:32:39+00:00
macosx: Set end of playback view by default to enabled
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
18 changed files:
- extras/package/macosx/VLC.xcodeproj/project.pbxproj
- modules/gui/macosx/Makefile.am
- modules/gui/macosx/UI/SimplePreferences.xib
- + modules/gui/macosx/UI/VLCPlaybackEndView.xib
- modules/gui/macosx/extensions/NSArray+VLCAdditions.h
- modules/gui/macosx/extensions/NSArray+VLCAdditions.m
- modules/gui/macosx/library/VLCInputItem.h
- modules/gui/macosx/library/VLCInputItem.m
- modules/gui/macosx/library/VLCLibraryWindow.m
- modules/gui/macosx/main/VLCMain+OldPrefs.m
- modules/gui/macosx/main/VLCMain.h
- modules/gui/macosx/main/VLCMain.m
- modules/gui/macosx/preferences/VLCSimplePrefsController.h
- modules/gui/macosx/preferences/VLCSimplePrefsController.m
- + modules/gui/macosx/views/VLCPlaybackEndViewController.h
- + modules/gui/macosx/views/VLCPlaybackEndViewController.m
- modules/gui/macosx/windows/video/VLCMainVideoViewController.h
- modules/gui/macosx/windows/video/VLCMainVideoViewController.m
Changes:
=====================================
extras/package/macosx/VLC.xcodeproj/project.pbxproj
=====================================
@@ -122,6 +122,7 @@
536BFD1929B181E100BD0776 /* VLCMainVideoViewOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 536BFD1829B181E100BD0776 /* VLCMainVideoViewOverlayView.m */; };
536EFBF5295BCB8300F4CB13 /* VLCLibraryUIUnits.m in Sources */ = {isa = PBXBuildFile; fileRef = 536EFBF4295BCB8300F4CB13 /* VLCLibraryUIUnits.m */; };
536EFC39295E521600F4CB13 /* VLCLibraryVideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 536EFC38295E521600F4CB13 /* VLCLibraryVideoViewController.m */; };
+ 537040DF2DD848440030ABF5 /* VLCPlaybackEndViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 537040DE2DD848440030ABF5 /* VLCPlaybackEndViewController.m */; };
5377B15C2BD12EEE00D660B8 /* QuickLookThumbnailing.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5377B15B2BD12EEE00D660B8 /* QuickLookThumbnailing.framework */; };
5377B15E2BD12F2900D660B8 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5377B15D2BD12F2900D660B8 /* QuickLook.framework */; };
537976BA2A4319330036827E /* VLCSettingTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 537976B82A4319330036827E /* VLCSettingTextField.m */; };
@@ -296,6 +297,7 @@
1CFE8D561EA0D3D300E94451 /* ErrorPanel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ErrorPanel.xib; sourceTree = "<group>"; };
1CFE8D571EA0D42A00E94451 /* VLCErrorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCErrorWindowController.h; sourceTree = "<group>"; };
1CFE8D581EA0D42A00E94451 /* VLCErrorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCErrorWindowController.m; sourceTree = "<group>"; };
+ 530429942DD1ED66004BB598 /* VLCPlaybackEndView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VLCPlaybackEndView.xib; sourceTree = "<group>"; };
530771F22AEBB80C00656D3D /* VLCLibraryRepresentedItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCLibraryRepresentedItem.h; sourceTree = "<group>"; };
530771F32AEBBD5B00656D3D /* VLCLibraryRepresentedItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryRepresentedItem.m; sourceTree = "<group>"; };
5307A6F32967859F001E0C6A /* NSImage+VLCAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSImage+VLCAdditions.h"; sourceTree = "<group>"; };
@@ -406,6 +408,8 @@
536EFC37295E521600F4CB13 /* VLCLibraryVideoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryVideoViewController.h; sourceTree = "<group>"; };
536EFC38295E521600F4CB13 /* VLCLibraryVideoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryVideoViewController.m; sourceTree = "<group>"; };
536EFC3A295F828000F4CB13 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+ 537040DD2DD848440030ABF5 /* VLCPlaybackEndViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackEndViewController.h; sourceTree = "<group>"; };
+ 537040DE2DD848440030ABF5 /* VLCPlaybackEndViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackEndViewController.m; sourceTree = "<group>"; };
5377B15B2BD12EEE00D660B8 /* QuickLookThumbnailing.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookThumbnailing.framework; path = System/Library/PrivateFrameworks/QuickLookThumbnailing.framework; sourceTree = SDKROOT; };
5377B15D2BD12F2900D660B8 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; };
537976B82A4319330036827E /* VLCSettingTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCSettingTextField.m; sourceTree = "<group>"; };
@@ -1157,6 +1161,8 @@
535053ED2B610C3400D7EAF2 /* VLCLoadingOverlayView.m */,
53CBE3092C159A4D006BF2E3 /* VLCNoResultsLabel.h */,
53CBE30A2C159A4D006BF2E3 /* VLCNoResultsLabel.m */,
+ 537040DD2DD848440030ABF5 /* VLCPlaybackEndViewController.h */,
+ 537040DE2DD848440030ABF5 /* VLCPlaybackEndViewController.m */,
6B0AB0EC1F1AC8B3003A1B4E /* VLCPlaybackProgressSlider.h */,
6B0AB0ED1F1AC8B3003A1B4E /* VLCPlaybackProgressSlider.m */,
6B0AB0EE1F1AC8B3003A1B4E /* VLCPlaybackProgressSliderCell.h */,
@@ -2126,6 +2132,7 @@
534E8E3729A04F95009503F8 /* VLCMainVideoView.xib */,
7D67318322C8F3F60000AD40 /* VLCMediaSourceCollectionViewItem.xib */,
7DF14FBC2270CB1C0008ABE4 /* VLCMediaSourceDeviceCollectionViewItem.xib */,
+ 530429942DD1ED66004BB598 /* VLCPlaybackEndView.xib */,
7D0F64002201F66D00FDB91F /* VLCPlayQueueTableCellView.xib */,
6B82241A1E4D2A9000833BE1 /* VLCStatusBarIconMainMenu.xib */,
7D713D332201BB130042BEB7 /* VLCLibraryWindow.xib */,
@@ -2272,6 +2279,7 @@
1CCC89022078A3D500E5626F /* ResumeDialog.xib in Sources */,
531062162CE259290087F863 /* VLCLibraryHomeViewActionButtonCell.m in Sources */,
532572032C3D79D80068DEC3 /* VLCLibrarySegmentBookmarkedLocation.m in Sources */,
+ 537040DF2DD848440030ABF5 /* VLCPlaybackEndViewController.m in Sources */,
7DE7232E22A51F8D00D72616 /* VLCPositionFormatter.m in Sources */,
534E8E3A29A06325009503F8 /* VLCMainVideoViewController.m in Sources */,
531062112CE1CB520087F863 /* VLCLibraryHomeViewActionsView.m in Sources */,
=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -395,6 +395,8 @@ libmacosx_plugin_la_SOURCES = \
gui/macosx/views/VLCLoadingOverlayView.m \
gui/macosx/views/VLCNoResultsLabel.h \
gui/macosx/views/VLCNoResultsLabel.m \
+ gui/macosx/views/VLCPlaybackEndViewController.h \
+ gui/macosx/views/VLCPlaybackEndViewController.m \
gui/macosx/views/VLCPlaybackProgressSlider.h \
gui/macosx/views/VLCPlaybackProgressSlider.m \
gui/macosx/views/VLCPlaybackProgressSliderCell.h \
@@ -512,6 +514,7 @@ libmacosx_plugin_la_XIB_SOURCES = \
gui/macosx/UI/VLCMediaSourceCollectionViewItem.xib \
gui/macosx/UI/VLCMediaSourceDeviceCollectionViewItem.xib \
gui/macosx/UI/VLCInformationWindow.xib \
+ gui/macosx/UI/VLCPlaybackEndView.xib \
gui/macosx/UI/Open.xib \
gui/macosx/UI/PlaylistAccessoryView.xib \
gui/macosx/UI/PopupPanel.xib \
=====================================
modules/gui/macosx/UI/SimplePreferences.xib
=====================================
@@ -61,6 +61,7 @@
<outlet property="intf_artCheckbox" destination="3928" id="HND-nW-BHK"/>
<outlet property="intf_continueplaybackLabel" destination="3919" id="ZJO-qY-UCq"/>
<outlet property="intf_continueplaybackPopup" destination="3920" id="dZ3-SI-SCp"/>
+ <outlet property="intf_displayEndOfPlaybackViewCheckBox" destination="SYi-7I-cKE" id="sTC-Oc-1zX"/>
<outlet property="intf_enableNotificationsCheckbox" destination="3564" id="IIA-ce-g61"/>
<outlet property="intf_enableluahttpCheckbox" destination="lpZ-9y-Vfn" id="ieR-ZH-mcd"/>
<outlet property="intf_generalSettingsBox" destination="kup-aY-Wqq" id="RsL-yE-DVe"/>
@@ -375,13 +376,26 @@ Gw
<action selector="interfaceSettingChanged:" target="-2" id="SxN-sI-55J"/>
</connections>
</popUpButton>
+ <button mirrorLayoutDirectionWhenInternationalizing="always" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SYi-7I-cKE">
+ <rect key="frame" x="15" y="14" width="201" height="18"/>
+ <buttonCell key="cell" type="check" title="Display end of playback view" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="Vsg-0v-H35">
+ <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="interfaceSettingChanged:" target="-2" id="SR0-g4-Kx9"/>
+ </connections>
+ </button>
</subviews>
<constraints>
- <constraint firstAttribute="bottom" secondItem="3920" secondAttribute="bottom" constant="15" id="11b-WT-SyB"/>
+ <constraint firstItem="SYi-7I-cKE" firstAttribute="leading" secondItem="gj4-zO-E26" secondAttribute="leading" constant="17" id="5SR-Aq-aAG"/>
+ <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="SYi-7I-cKE" secondAttribute="trailing" constant="17" id="5a5-Eq-PCg"/>
<constraint firstAttribute="trailing" secondItem="3920" secondAttribute="trailing" constant="17" id="M7f-H3-4Mk"/>
<constraint firstItem="3919" firstAttribute="top" secondItem="gj4-zO-E26" secondAttribute="top" constant="12" id="R4h-Ob-XbD"/>
<constraint firstItem="3919" firstAttribute="centerY" secondItem="3920" secondAttribute="centerY" id="Txp-Vc-Bet"/>
<constraint firstItem="3919" firstAttribute="leading" secondItem="gj4-zO-E26" secondAttribute="leading" constant="17" id="cnI-H9-J0k"/>
+ <constraint firstItem="SYi-7I-cKE" firstAttribute="top" secondItem="3919" secondAttribute="bottom" constant="10" id="czT-2q-qcN"/>
+ <constraint firstAttribute="bottom" secondItem="SYi-7I-cKE" secondAttribute="bottom" constant="15" id="d1m-O6-Uxb"/>
<constraint firstItem="3920" firstAttribute="leading" secondItem="3919" secondAttribute="trailing" constant="17" id="gLu-nZ-tla"/>
</constraints>
</view>
=====================================
modules/gui/macosx/UI/VLCPlaybackEndView.xib
=====================================
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="VLCPlaybackEndViewController">
+ <connections>
+ <outlet property="countdownLabel" destination="C5J-Xc-NJc" id="tNP-DB-pOU"/>
+ <outlet property="largeTitleLabel" destination="jN5-TU-5uH" id="0qd-aL-HsE"/>
+ <outlet property="playNextItemButton" destination="YFo-7r-UzM" id="ZrY-Ot-LjJ"/>
+ <outlet property="restartPlayQueueButton" destination="CII-HN-I8g" id="uLY-jC-xYO"/>
+ <outlet property="returnToLibraryButton" destination="vpB-Yh-v5U" id="e37-g6-GGT"/>
+ <outlet property="view" destination="NcL-Nn-hUb" id="do2-eJ-8gU"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+ <visualEffectView wantsLayer="YES" blendingMode="withinWindow" material="sheet" state="followsWindowActiveState" translatesAutoresizingMaskIntoConstraints="NO" id="NcL-Nn-hUb">
+ <rect key="frame" x="0.0" y="0.0" width="432" height="149"/>
+ <subviews>
+ <textField focusRingType="none" horizontalHuggingPriority="1000" verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="jN5-TU-5uH">
+ <rect key="frame" x="18" y="98" width="396" height="31"/>
+ <textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Reached the end of the play queue" id="FXe-a6-cQO">
+ <font key="font" textStyle="largeTitle" name=".SFNS-Regular"/>
+ <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="C5J-Xc-NJc">
+ <rect key="frame" x="18" y="72" width="396" height="16"/>
+ <textFieldCell key="cell" alignment="center" title="Returning to library in X seconds" id="eII-yp-Ukx">
+ <font key="font" textStyle="headline" name=".SFNS-Bold"/>
+ <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <stackView distribution="fillEqually" orientation="horizontal" alignment="top" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="huG-UY-8W9">
+ <rect key="frame" x="20" y="20" width="392" height="32"/>
+ <subviews>
+ <button wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vpB-Yh-v5U">
+ <rect key="frame" x="0.0" y="0.0" width="125" height="32"/>
+ <buttonCell key="cell" type="inline" title="Return to library" bezelStyle="inline" image="books.vertical.fill" catalog="system" imagePosition="above" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ZPD-Ry-835">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="smallSystemBold"/>
+ </buttonCell>
+ </button>
+ <button wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CII-HN-I8g">
+ <rect key="frame" x="133" y="0.0" width="126" height="32"/>
+ <buttonCell key="cell" type="inline" title="Restart play queue" bezelStyle="inline" image="repeat" catalog="system" imagePosition="above" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="DVf-m9-gWa">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="smallSystemBold"/>
+ </buttonCell>
+ </button>
+ <button wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YFo-7r-UzM">
+ <rect key="frame" x="267" y="0.0" width="125" height="32"/>
+ <buttonCell key="cell" type="inline" title="Play next item" bezelStyle="inline" image="arrow.right" catalog="system" imagePosition="above" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="O5u-Ck-U6T">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" size="11" name=".SFNS-Semibold"/>
+ </buttonCell>
+ </button>
+ </subviews>
+ <visibilityPriorities>
+ <integer value="1000"/>
+ <integer value="1000"/>
+ <integer value="1000"/>
+ </visibilityPriorities>
+ <customSpacing>
+ <real value="3.4028234663852886e+38"/>
+ <real value="3.4028234663852886e+38"/>
+ <real value="3.4028234663852886e+38"/>
+ </customSpacing>
+ </stackView>
+ </subviews>
+ <constraints>
+ <constraint firstItem="C5J-Xc-NJc" firstAttribute="centerX" secondItem="NcL-Nn-hUb" secondAttribute="centerX" id="6R0-qc-UGn"/>
+ <constraint firstItem="huG-UY-8W9" firstAttribute="leading" secondItem="jN5-TU-5uH" secondAttribute="leading" id="8qx-OA-DDQ"/>
+ <constraint firstItem="jN5-TU-5uH" firstAttribute="top" secondItem="NcL-Nn-hUb" secondAttribute="top" constant="20" id="Bae-6M-XVS"/>
+ <constraint firstItem="jN5-TU-5uH" firstAttribute="centerX" secondItem="NcL-Nn-hUb" secondAttribute="centerX" id="M51-kv-EP2"/>
+ <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="huG-UY-8W9" secondAttribute="trailing" constant="20" id="MbH-DN-TXI"/>
+ <constraint firstItem="huG-UY-8W9" firstAttribute="trailing" secondItem="jN5-TU-5uH" secondAttribute="trailing" id="Q7l-NQ-MIx"/>
+ <constraint firstItem="jN5-TU-5uH" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="NcL-Nn-hUb" secondAttribute="leading" constant="20" id="SWK-YP-EHJ"/>
+ <constraint firstItem="C5J-Xc-NJc" firstAttribute="trailing" secondItem="jN5-TU-5uH" secondAttribute="trailing" id="UgU-D1-V5D"/>
+ <constraint firstItem="C5J-Xc-NJc" firstAttribute="top" secondItem="jN5-TU-5uH" secondAttribute="bottom" constant="10" id="VgY-k7-miC"/>
+ <constraint firstItem="huG-UY-8W9" firstAttribute="top" secondItem="C5J-Xc-NJc" secondAttribute="bottom" constant="20" id="Wk4-Fh-M3Z"/>
+ <constraint firstItem="huG-UY-8W9" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="NcL-Nn-hUb" secondAttribute="leading" constant="20" id="X0f-L9-A1Y"/>
+ <constraint firstItem="C5J-Xc-NJc" firstAttribute="leading" secondItem="jN5-TU-5uH" secondAttribute="leading" id="Y4B-nN-ley"/>
+ <constraint firstItem="huG-UY-8W9" firstAttribute="centerX" secondItem="NcL-Nn-hUb" secondAttribute="centerX" id="mVr-Ig-tg3"/>
+ <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="jN5-TU-5uH" secondAttribute="trailing" constant="20" id="nWw-9e-tGN"/>
+ <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="149" id="owb-PL-E4y"/>
+ <constraint firstAttribute="bottom" secondItem="huG-UY-8W9" secondAttribute="bottom" constant="20" id="paw-6c-QHp"/>
+ </constraints>
+ <point key="canvasLocation" x="286" y="184.5"/>
+ </visualEffectView>
+ </objects>
+ <resources>
+ <image name="arrow.right" catalog="system" width="15" height="12"/>
+ <image name="books.vertical.fill" catalog="system" width="20" height="17"/>
+ <image name="repeat" catalog="system" width="18" height="14"/>
+ </resources>
+</document>
=====================================
modules/gui/macosx/extensions/NSArray+VLCAdditions.h
=====================================
@@ -31,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface NSArray (VLCAdditions)
+ (NSArray<VLCMediaLibraryMediaItem *> *)arrayFromVlcMediaList:(vlc_ml_media_list_t *)p_media_list;
+- (NSInteger)indexOfMediaLibraryItem:(id<VLCMediaLibraryItemProtocol>)mediaLibraryItem;
@end
=====================================
modules/gui/macosx/extensions/NSArray+VLCAdditions.m
=====================================
@@ -40,4 +40,12 @@
return mutableArray.copy;
}
+- (NSInteger)indexOfMediaLibraryItem:(id<VLCMediaLibraryItemProtocol>)mediaLibraryItem
+{
+ return [self indexOfObjectPassingTest:^BOOL(const id<VLCMediaLibraryItemProtocol> item, const NSUInteger idx, BOOL * const stop) {
+ NSParameterAssert([item conformsToProtocol:@protocol(VLCMediaLibraryItemProtocol)]);
+ return item.libraryID == mediaLibraryItem.libraryID;
+ }];
+}
+
@end
=====================================
modules/gui/macosx/library/VLCInputItem.h
=====================================
@@ -41,6 +41,7 @@ extern NSString * const VLCInputItemCommonDataDifferingFlagString;
@interface VLCInputItem : NSObject<VLCLocallyManipulableItemProtocol>
++ (nullable instancetype)inputItemFromURL:(NSURL *)url;
- (instancetype)initWithInputItem:(struct input_item_t *)p_inputItem;
@property (readonly) struct input_item_t *vlcInputItem;
=====================================
modules/gui/macosx/library/VLCInputItem.m
=====================================
@@ -74,6 +74,18 @@ static const struct input_item_parser_cbs_t parserCallbacks =
@implementation VLCInputItem
++ (nullable instancetype)inputItemFromURL:(NSURL *)url
+{
+ const char * const psz_uri = url.absoluteString.UTF8String;
+ const char * const psz_name = url.lastPathComponent.stringByDeletingPathExtension.UTF8String;
+ input_item_t * const p_input_item = input_item_New(psz_uri, psz_name);
+ if (p_input_item == NULL)
+ return nil;
+ VLCInputItem * const inputItem = [[VLCInputItem alloc] initWithInputItem:p_input_item];
+ input_item_Release(p_input_item);
+ return inputItem;
+}
+
- (instancetype)initWithInputItem:(struct input_item_t *)p_inputItem
{
self = [super init];
=====================================
modules/gui/macosx/library/VLCLibraryWindow.m
=====================================
@@ -76,6 +76,7 @@
#import "views/VLCImageView.h"
#import "views/VLCLoadingOverlayView.h"
#import "views/VLCNoResultsLabel.h"
+#import "views/VLCPlaybackEndViewController.h"
#import "views/VLCRoundedCornerTextField.h"
#import "views/VLCTrackingView.h"
@@ -412,7 +413,9 @@ static void addShadow(NSImageView *__unsafe_unretained imageView)
VLCMediaLibraryMediaItem * const mediaItem = [VLCMediaLibraryMediaItem mediaItemForURL:currentMediaUrl];
const BOOL decorativeViewVisible = mediaItem != nil && mediaItem.mediaType == VLC_ML_MEDIA_TYPE_AUDIO;
- if (!decorativeViewVisible) {
+ if (!decorativeViewVisible && [NSUserDefaults.standardUserDefaults boolForKey:VLCPlaybackEndViewEnabledKey]) {
+ [self.videoViewController displayPlaybackEndView];
+ } else if (!decorativeViewVisible) {
[self disableVideoPlaybackAppearance];
}
} else {
=====================================
modules/gui/macosx/main/VLCMain+OldPrefs.m
=====================================
@@ -34,7 +34,6 @@
@implementation VLCMain(OldPrefs)
-static NSString * kVLCPreferencesVersion = @"VLCPreferencesVersion";
static const int kCurrentPreferencesVersion = 4;
+ (void)initialize
=====================================
modules/gui/macosx/main/VLCMain.h
=====================================
@@ -42,6 +42,7 @@ intf_thread_t *getIntf(void);
vlc_preparser_t *getNetworkPreparser();
extern NSString *VLCConfigurationChangedNotification;
+extern NSString * const kVLCPreferencesVersion;
/*****************************************************************************
* VLCMain interface
=====================================
modules/gui/macosx/main/VLCMain.m
=====================================
@@ -73,6 +73,8 @@
#import "preferences/prefs.h"
#import "preferences/VLCSimplePrefsController.h"
+#import "views/VLCPlaybackEndViewController.h"
+
#import "windows/VLCDetachedAudioWindow.h"
#import "windows/VLCOpenWindowController.h"
#import "windows/VLCOpenInputMetadata.h"
@@ -90,6 +92,8 @@ NSString *const kARM64UpdateURLString = @"https://update.videolan.org/vlc/sparkl
NSString *VLCConfigurationChangedNotification = @"VLCConfigurationChangedNotification";
+NSString * const kVLCPreferencesVersion = @"VLCPreferencesVersion";
+
#pragma mark -
#pragma mark Private extension
@@ -308,7 +312,11 @@ static VLCMain *sharedInstance = nil;
if (!_p_intf)
return;
- [self migrateOldPreferences];
+ NSUserDefaults * const defaults = NSUserDefaults.standardUserDefaults;
+ if ([defaults integerForKey:kVLCPreferencesVersion] != 4) {
+ [defaults setBool:YES forKey:VLCPlaybackEndViewEnabledKey];
+ [self migrateOldPreferences];
+ }
_statusBarIcon = [[VLCStatusBarIcon alloc] init];
=====================================
modules/gui/macosx/preferences/VLCSimplePrefsController.h
=====================================
@@ -118,6 +118,7 @@
@property (readwrite, weak) IBOutlet NSBox *intf_playbackControlBox;
@property (readwrite, weak) IBOutlet NSTextField *intf_continueplaybackLabel;
@property (readwrite, weak) IBOutlet NSPopUpButton *intf_continueplaybackPopup;
+ at property (readwrite, weak) IBOutlet NSButton *intf_displayEndOfPlaybackViewCheckBox;
// intf pane - behaviour box
@property (readwrite, weak) IBOutlet NSBox *intf_playbackBehaviourBox;
=====================================
modules/gui/macosx/preferences/VLCSimplePrefsController.m
=====================================
@@ -50,6 +50,7 @@
#import "library/VLCLibraryController.h"
#import "library/VLCLibraryModel.h"
#import "library/VLCLibraryDataTypes.h"
+#import "views/VLCPlaybackEndViewController.h"
static struct {
const char iso[6];
@@ -400,6 +401,7 @@ create_toolbar_item(NSString *itemIdent, NSString *name, NSString *desc, NSStrin
[_intf_playbackControlBox setTitle:_NS("Playback control")];
[_intf_continueplaybackLabel setStringValue:_NS("Continue playback")];
+ [_intf_displayEndOfPlaybackViewCheckBox setTitle:_NS("Display end of playback view")];
[_intf_statusIconCheckbox setTitle: _NS("Display VLC status menu icon")];
[_intf_largeFontInListsCheckbox setTitle: _NS("Use large text for list views")];
@@ -608,7 +610,8 @@ create_toolbar_item(NSString *itemIdent, NSString *name, NSString *desc, NSStrin
**********************/
NSUInteger sel = 0;
const char *pref = NULL;
- pref = [[[NSUserDefaults standardUserDefaults] objectForKey:@"language"] UTF8String];
+ NSUserDefaults * const defaults = NSUserDefaults.standardUserDefaults;
+ pref = [[defaults objectForKey:@"language"] UTF8String];
for (int x = 0; x < ARRAY_SIZE(language_map); x++) {
[_intf_languagePopup addItemWithTitle:toNSStr(language_map[x].name)];
if (pref) {
@@ -626,6 +629,8 @@ create_toolbar_item(NSString *itemIdent, NSString *name, NSString *desc, NSStrin
[_intf_continueplaybackPopup setEnabled: YES];
}
+ self.intf_displayEndOfPlaybackViewCheckBox.state = [defaults boolForKey:VLCPlaybackEndViewEnabledKey] ? NSControlStateValueOn : NSControlStateValueOff;
+
[self setupButton:_intf_statusIconCheckbox forBoolValue: "macosx-statusicon"];
[self setupButton:_video_nativeFullscreenCheckbox forBoolValue: "macosx-nativefullscreenmode"];
@@ -952,6 +957,9 @@ static inline void save_string_list(intf_thread_t * p_intf, id object, const cha
[defaults setObject:toNSStr(language_map[index].iso) forKey:@"language"];
[VLCSimplePrefsController updateRightToLeftSettings];
+ [defaults setBool:self.intf_displayEndOfPlaybackViewCheckBox.state == NSControlStateValueOn
+ forKey:VLCPlaybackEndViewEnabledKey];
+
config_PutInt("metadata-network-access", [_intf_artCheckbox state]);
config_PutInt("macosx-statusicon", [_intf_statusIconCheckbox state]);
=====================================
modules/gui/macosx/views/VLCPlaybackEndViewController.h
=====================================
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * VLCPlaybackEndViewController.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 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
+
+extern NSString * const VLCPlaybackEndViewEnabledKey;
+extern NSString * const VLCPlaybackEndViewReturnToLibraryNotificationName;
+extern NSString * const VLCPlaybackEndViewHideNotificationName;
+
+ at interface VLCPlaybackEndViewController : NSViewController
+
+ at property (readwrite, weak) IBOutlet NSTextField *largeTitleLabel;
+ at property (readwrite, weak) IBOutlet NSTextField *countdownLabel;
+ at property (readwrite, weak) IBOutlet NSButton *returnToLibraryButton;
+ at property (readwrite, weak) IBOutlet NSButton *restartPlayQueueButton;
+ at property (readwrite, weak) IBOutlet NSButton *playNextItemButton;
+ at property (readwrite, nonatomic) BOOL hideLibraryControls;
+ at property (readonly) NSTimer *countdownTimer;
+
+- (void)startCountdown;
+
+ at end
+
+NS_ASSUME_NONNULL_END
=====================================
modules/gui/macosx/views/VLCPlaybackEndViewController.m
=====================================
@@ -0,0 +1,234 @@
+/*****************************************************************************
+ * VLCPlaybackEndViewController.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 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 "VLCPlaybackEndViewController.h"
+
+#import "main/VLCMain.h"
+#import "extensions/NSArray+VLCAdditions.h"
+#import "extensions/NSColor+VLCAdditions.h"
+#import "extensions/NSString+Helpers.h"
+#import "library/VLCInputItem.h"
+#import "library/VLCLibraryController.h"
+#import "library/VLCLibraryModel.h"
+#import "library/VLCLibraryUIUnits.h"
+#import "playqueue/VLCPlayQueueController.h"
+
+static const NSTimeInterval kVLCPlaybackEndTimeout = 10;
+static const NSTimeInterval kVLCPlaybackEndUpdateInterval = 0.1;
+
+NSString * const VLCPlaybackEndViewEnabledKey = @"VLCPlaybackEndViewEnabledKey";
+NSString * const VLCPlaybackEndViewHideNotificationName = @"VLCPlaybackEndViewRequestHide";
+NSString * const VLCPlaybackEndViewReturnToLibraryNotificationName = @"VLCPlaybackEndViewReturnToLibrary";
+
+ at interface VLCPlaybackEndViewController ()
+
+ at property NSDate *timeoutDate;
+ at property VLCInputItem *nextItem;
+
+ at end
+
+ at implementation VLCPlaybackEndViewController
+
+- (instancetype)init
+{
+ return [super initWithNibName:@"VLCPlaybackEndView" bundle:nil];
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.view.wantsLayer = YES;
+ self.view.layer.cornerRadius = VLCLibraryUIUnits.cornerRadius;
+ self.view.layer.borderColor = NSColor.VLCSubtleBorderColor.CGColor;
+ self.view.layer.borderWidth = VLCLibraryUIUnits.borderThickness;
+ self.largeTitleLabel.stringValue = _NS("Reached the end of the play queue");
+ self.returnToLibraryButton.stringValue = _NS("Return to library");
+ self.returnToLibraryButton.target = self;
+ self.returnToLibraryButton.action = @selector(returnToLibrary:);
+ self.restartPlayQueueButton.stringValue = _NS("Restart play queue");
+ self.restartPlayQueueButton.target = self;
+ self.restartPlayQueueButton.action = @selector(restartPlayQueue:);
+ self.playNextItemButton.stringValue = _NS("Play next item");
+ self.playNextItemButton.target = self;
+ self.playNextItemButton.action = @selector(playNextItem:);
+}
+
+- (void)startCountdown
+{
+ [self.countdownTimer invalidate];
+
+ VLCInputItem * const currentInputItem =
+ VLCMain.sharedInstance.playQueueController.currentlyPlayingInputItem;
+ NSURL * const inputItemUrl = [NSURL URLWithString:currentInputItem.MRL];
+ VLCMediaLibraryMediaItem * const mediaLibraryItem =
+ [VLCMediaLibraryMediaItem mediaItemForURL:inputItemUrl];
+
+ if (mediaLibraryItem) {
+ self.nextItem = [self nextItemForMediaLibraryItem:mediaLibraryItem];
+ } else {
+ self.nextItem = [self nextItemForInputItem:currentInputItem];
+ }
+ self.playNextItemButton.hidden = self.nextItem == nil;
+ self.timeoutDate = [NSDate dateWithTimeIntervalSinceNow:kVLCPlaybackEndTimeout];
+ _countdownTimer = [NSTimer scheduledTimerWithTimeInterval:kVLCPlaybackEndUpdateInterval
+ target:self
+ selector:@selector(handleUpdateInterval:)
+ userInfo:nil
+ repeats:YES];
+ [self handleUpdateInterval:nil];
+}
+
+- (nullable VLCInputItem *)nextItemForMediaLibraryItem:(VLCMediaLibraryMediaItem *)item
+{
+ NSArray<VLCMediaLibraryMediaItem *> *parentMediaItemCollection = nil;
+ __block NSInteger itemIndex = NSNotFound;
+
+ if (item.mediaSubType == VLC_ML_MEDIA_SUBTYPE_ALBUMTRACK) {
+ parentMediaItemCollection = [VLCMediaLibraryAlbum albumWithID:item.albumID].mediaItems;
+ itemIndex = [parentMediaItemCollection indexOfMediaLibraryItem:item];
+ } else if (item.mediaSubType == VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE) {
+ NSArray<VLCMediaLibraryShow *> * const shows =
+ VLCMain.sharedInstance.libraryController.libraryModel.listOfShows;
+ const NSInteger showContainingEpisodeIdx = [shows indexOfObjectPassingTest:^BOOL(VLCMediaLibraryShow * const show, const NSUInteger idx, BOOL * const stop) {
+ itemIndex = [show.mediaItems indexOfMediaLibraryItem:item];
+ return itemIndex != NSNotFound;
+ }];
+ if (showContainingEpisodeIdx != NSNotFound) {
+ parentMediaItemCollection = shows[showContainingEpisodeIdx].mediaItems;
+ }
+ }
+
+ if (parentMediaItemCollection == nil ||
+ itemIndex == NSNotFound ||
+ itemIndex + 1 >= parentMediaItemCollection.count
+ ) {
+ return [self nextItemForInputItem:item.inputItem];
+ }
+ return parentMediaItemCollection[itemIndex + 1].inputItem;
+}
+
+- (nullable VLCInputItem *)nextItemForInputItem:(VLCInputItem *)item
+{
+ if (item.isStream) {
+ return nil;
+ }
+
+ NSURL * const itemUrl = [NSURL URLWithString:item.MRL];
+ NSParameterAssert(itemUrl != nil);
+ NSString * const parentFolderPath = itemUrl.URLByDeletingLastPathComponent.path;
+ NSFileManager * const fm = NSFileManager.defaultManager;
+ NSError *error = nil;
+ NSArray<NSString *> * const itemSiblingItemPaths =
+ [fm contentsOfDirectoryAtPath:parentFolderPath error:&error];
+
+ if (error != nil) {
+ NSLog(@"Could not find siblings for item: %@\n\tReceived error:%@", item.decodedMRL, error.localizedDescription);
+ return nil;
+ }
+
+ const NSInteger itemIdx = [itemSiblingItemPaths indexOfObject:itemUrl.lastPathComponent];
+ NSParameterAssert(itemIdx != NSNotFound);
+ if (itemIdx + 1 >= itemSiblingItemPaths.count) {
+ NSLog(@"Played item was last in parent folder.");
+ return nil;
+ }
+ NSString * const nextItemFileName = itemSiblingItemPaths[itemIdx + 1];
+ NSURL * const nextItemURL =
+ [[NSURL fileURLWithPath:parentFolderPath] URLByAppendingPathComponent:nextItemFileName];
+ return [VLCInputItem inputItemFromURL:nextItemURL];
+}
+
+- (void)handleUpdateInterval:(nullable NSTimer *)timer
+{
+ NSDate * const now = NSDate.date;
+ NSDate * const timeout = self.timeoutDate;
+ const NSTimeInterval timeRemaining = [timeout timeIntervalSinceDate:now];
+ if (timeRemaining <= 0) {
+ if (self.nextItem) {
+ [self playNextItem:self];
+ } else {
+ [self returnToLibrary:self];
+ }
+ return;
+ }
+
+ NSString *remainingTimeString = @"";
+ if (@available(macOS 10.15, *)) {
+ NSRelativeDateTimeFormatter * const formatter = [[NSRelativeDateTimeFormatter alloc] init];
+ remainingTimeString = [formatter localizedStringForDate:timeout relativeToDate:now];
+ } else {
+ NSDateComponentsFormatter * const formatter = [[NSDateComponentsFormatter alloc] init];
+ NSString * const timeString = [formatter stringFromTimeInterval:timeRemaining];
+ remainingTimeString = [NSString stringWithFormat:_NS("in %@"), timeString];
+ }
+
+ NSString *countdownLabelString = nil;
+ if (self.nextItem) {
+ countdownLabelString =
+ [NSString stringWithFormat:_NS("Playing %@ %@"), self.nextItem.title, remainingTimeString];
+ } else {
+ countdownLabelString =
+ [NSString stringWithFormat:_NS("Returning to library %@"), remainingTimeString];
+ }
+ NSParameterAssert(countdownLabelString != nil);
+ self.countdownLabel.stringValue = countdownLabelString;
+}
+
+- (void)setHideLibraryControls:(BOOL)hideLibraryControls
+{
+ if (self.hideLibraryControls == hideLibraryControls)
+ return;
+ _hideLibraryControls = hideLibraryControls;
+ self.countdownLabel.hidden = hideLibraryControls;
+ self.returnToLibraryButton.hidden = hideLibraryControls;
+}
+
+- (void)returnToLibrary:(id)sender
+{
+ [self.countdownTimer invalidate];
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCPlaybackEndViewReturnToLibraryNotificationName
+ object:self];
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCPlaybackEndViewHideNotificationName
+ object:self];
+}
+
+- (void)restartPlayQueue:(id)sender
+{
+ [self.countdownTimer invalidate];
+ [VLCMain.sharedInstance.playQueueController playItemAtIndex:0];
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCPlaybackEndViewHideNotificationName
+ object:self];
+}
+
+- (void)playNextItem:(id)sender
+{
+ [self.countdownTimer invalidate];
+ if (self.nextItem == nil)
+ return;
+ [VLCMain.sharedInstance.playQueueController addInputItem:self.nextItem.vlcInputItem
+ atPosition:-1
+ startPlayback:YES];
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCPlaybackEndViewHideNotificationName
+ object:self];
+}
+
+ at end
=====================================
modules/gui/macosx/windows/video/VLCMainVideoViewController.h
=====================================
@@ -27,6 +27,7 @@
@class VLCMainVideoViewOverlayView;
@class VLCMainVideoViewAudioMediaDecorativeView;
@class VLCMainVideoViewControlsBar;
+ at class VLCPlaybackEndViewController;
NS_ASSUME_NONNULL_BEGIN
@@ -64,10 +65,13 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) BOOL mouseOnControls;
@property (readonly) BOOL pipIsActive;
+ at property (readonly) VLCPlaybackEndViewController *playbackEndViewController;
+
- (void)showControls;
- (void)hideControls;
- (nullable NSView *)acquireVideoView;
- (void)returnVideoView:(NSView *)videoView;
+- (void)displayPlaybackEndView;
- (IBAction)togglePlayQueue:(id)sender;
- (IBAction)returnToLibrary:(id)sender;
=====================================
modules/gui/macosx/windows/video/VLCMainVideoViewController.m
=====================================
@@ -39,6 +39,7 @@
#import "playqueue/VLCPlayerController.h"
#import "views/VLCBottomBarView.h"
+#import "views/VLCPlaybackEndViewController.h"
#import "windows/controlsbar/VLCMainVideoViewControlsBar.h"
@@ -552,6 +553,10 @@
- (IBAction)returnToLibrary:(id)sender
{
+ if (self.playbackEndViewController) { // Stop any pending automatic return to library
+ [self.playbackEndViewController.countdownTimer invalidate];
+ [self.playbackEndViewController.view removeFromSuperview];
+ }
VLCLibraryWindow *libraryWindow = (VLCLibraryWindow*)self.view.window;
if (libraryWindow != nil) {
[libraryWindow disableVideoPlaybackAppearance];
@@ -575,6 +580,41 @@
[self applyAudioDecorativeViewForegroundCoverArtViewConstraints];
}
+- (void)displayPlaybackEndView
+{
+ if (_playbackEndViewController == nil) {
+ _playbackEndViewController = [[VLCPlaybackEndViewController alloc] init];
+
+ NSNotificationCenter * const defaultCenter = NSNotificationCenter.defaultCenter;
+ [defaultCenter addObserver:self
+ selector:@selector(playbackEndViewReturnToLibrary:)
+ name:VLCPlaybackEndViewReturnToLibraryNotificationName
+ object:self.playbackEndViewController];
+ [defaultCenter addObserver:self
+ selector:@selector(playbackEndViewHide:)
+ name:VLCPlaybackEndViewHideNotificationName
+ object:self.playbackEndViewController];
+ }
+
+ self.playbackEndViewController.hideLibraryControls = !self.displayLibraryControls;
+ [self.view addSubview:self.playbackEndViewController.view];
+ [self.playbackEndViewController.view.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
+ [self.playbackEndViewController.view.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor].active = YES;
+ [self.playbackEndViewController.view.leadingAnchor constraintGreaterThanOrEqualToAnchor:self.view.leadingAnchor].active = YES;
+ [self.playbackEndViewController.view.trailingAnchor constraintLessThanOrEqualToAnchor:self.view.trailingAnchor].active = YES;
+ [self.playbackEndViewController startCountdown];
+}
+
+- (void)playbackEndViewReturnToLibrary:(NSNotification *)notification
+{
+ [self returnToLibrary:self];
+}
+
+- (void)playbackEndViewHide:(NSNotification *)notification
+{
+ [self.playbackEndViewController.view removeFromSuperview];
+}
+
#pragma mark - PIPViewControllerDelegate
- (BOOL)pipShouldClose:(PIPViewController *)pip
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/03514737e8afe2461efa7612726cb0d669644137...b65d5ca6c6bc70655b7fad09256e9088345f663e
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/03514737e8afe2461efa7612726cb0d669644137...b65d5ca6c6bc70655b7fad09256e9088345f663e
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