Title: [264663] trunk
Revision
264663
Author
eric.carl...@apple.com
Date
2020-07-21 10:46:28 -0700 (Tue, 21 Jul 2020)

Log Message

Use AVRoutePickerView when available for choosing AirPlay devices
https://bugs.webkit.org/show_bug.cgi?id=213497
<rdar://problem/58610662>

Reviewed by Jer Noble.

Source/WebCore:

Use an AVRoutePickerView, the replacement for AVOutputDeviceMenuController, when
it is available to allow a user to pick an AirPlay device. To do this, create an
AVPlaybackTargetPicker abstract base and create a concrete class from the
AVOutputDeviceMenuController-specific code from MediaPlaybackTargetPickerMac, and
create a new concrete class using AVRoutePickerView.

Tested manually because these changes require an AirPlay device.

* Modules/mediasession/WebMediaSessionManager.cpp:
(WebCore::WebMediaSessionManager::showPlaybackTargetPicker): Pass the view to the
target picker.
* Modules/mediasession/WebMediaSessionManagerClient.h:

* Modules/remoteplayback/RemotePlayback.cpp:
(WebCore::RemotePlayback::playbackTargetPickerWasDismissed): Drive-by fix: return
early if there are no pending promises.

* SourcesCocoa.txt: Add new files.
* WebCore.xcodeproj/project.pbxproj: Ditto.

* platform/graphics/MediaPlaybackTargetPicker.cpp:
(WebCore::MediaPlaybackTargetPicker::showPlaybackTargetPicker): Add new parameter.
* platform/graphics/MediaPlaybackTargetPicker.h:

* platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.h: Copied from Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h.
* platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.mm: Copied from Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm.
(WebCore::AVOutputDeviceMenuControllerTargetPicker::AVOutputDeviceMenuControllerTargetPicker):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::~AVOutputDeviceMenuControllerTargetPicker):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::devicePicker):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::availableDevicesDidChange):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::currentDeviceDidChange):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::showPlaybackTargetPicker):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::startingMonitoringPlaybackTargets):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::stopMonitoringPlaybackTargets):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::invalidatePlaybackTargets):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::externalOutputDeviceAvailable):
(WebCore::AVOutputDeviceMenuControllerTargetPicker::outputContext):
(-[WebAVOutputDeviceMenuControllerHelper initWithCallback:]):
(-[WebAVOutputDeviceMenuControllerHelper clearCallback]):
(-[WebAVOutputDeviceMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]):

* platform/graphics/avfoundation/objc/AVPlaybackTargetPicker.h: Added.
(WebCore::AVPlaybackTargetPicker::AVPlaybackTargetPicker):
(WebCore::AVPlaybackTargetPicker::client const):

* platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.h: Added.
* platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.mm: Added.
(WebCore::AVRoutePickerViewTargetPicker::isAvailable):
(WebCore::AVRoutePickerViewTargetPicker::AVRoutePickerViewTargetPicker):
(WebCore::AVRoutePickerViewTargetPicker::~AVRoutePickerViewTargetPicker):
(WebCore::AVRoutePickerViewTargetPicker::outputContextInternal):
(WebCore::AVRoutePickerViewTargetPicker::devicePicker):
(WebCore::AVRoutePickerViewTargetPicker::routeDetector):
(WebCore::AVRoutePickerViewTargetPicker::showPlaybackTargetPicker):
(WebCore::AVRoutePickerViewTargetPicker::startingMonitoringPlaybackTargets):
(WebCore::AVRoutePickerViewTargetPicker::stopMonitoringPlaybackTargets):
(WebCore::AVRoutePickerViewTargetPicker::externalOutputDeviceAvailable):
(WebCore::AVRoutePickerViewTargetPicker::outputContext):
(WebCore::AVRoutePickerViewTargetPicker::invalidatePlaybackTargets):
(WebCore::AVRoutePickerViewTargetPicker::availableDevicesDidChange):
(WebCore::AVRoutePickerViewTargetPicker::currentDeviceDidChange):
(WebCore::AVRoutePickerViewTargetPicker::devicePickerWasDismissed):
(-[WebAVRoutePickerViewHelper initWithCallback:]):
(-[WebAVRoutePickerViewHelper dealloc]):
(-[WebAVRoutePickerViewHelper clearCallback]):
(-[WebAVRoutePickerViewHelper routePickerViewDidEndPresentingRoutes:]):
(-[WebAVRoutePickerViewHelper notificationHandler:]):

* platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h:
* platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm:
(WebCore::MediaPlaybackTargetPickerMac::MediaPlaybackTargetPickerMac):
(WebCore::MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac):
(WebCore::MediaPlaybackTargetPickerMac::externalOutputDeviceAvailable):
(WebCore::MediaPlaybackTargetPickerMac::playbackTarget):
(WebCore::MediaPlaybackTargetPickerMac::routePicker):
(WebCore::MediaPlaybackTargetPickerMac::showPlaybackTargetPicker):
(WebCore::MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMac::invalidatePlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMac::pickerWasDismissed):
(WebCore::MediaPlaybackTargetPickerMac::availableDevicesChanged):
(WebCore::MediaPlaybackTargetPickerMac::currentDeviceChanged):
(WebCore::MediaPlaybackTargetPickerMac::devicePicker): Deleted.
(-[WebAVOutputDeviceMenuControllerHelper initWithCallback:]): Deleted.
(-[WebAVOutputDeviceMenuControllerHelper clearCallback]): Deleted.
(-[WebAVOutputDeviceMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]): Deleted.
* platform/mock/MediaPlaybackTargetPickerMock.cpp:
(WebCore::MediaPlaybackTargetPickerMock::showPlaybackTargetPicker):
* platform/mock/MediaPlaybackTargetPickerMock.h:

Source/WebCore/PAL:

* pal/cocoa/AVFoundationSoftLink.h:
* pal/cocoa/AVFoundationSoftLink.mm: Soft link AVRoutePickerView.
* pal/spi/cocoa/AVKitSPI.h: Declare AVRoutePickerView.

Source/WebKit:

* UIProcess/WebPageProxy.h:
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::platformView const): Add new override.

Source/WebKitLegacy/mac:

* WebView/WebMediaPlaybackTargetPicker.h:
(WebMediaPlaybackTargetPicker::~WebMediaPlaybackTargetPicker): Deleted.
* WebView/WebMediaPlaybackTargetPicker.mm:
(WebMediaPlaybackTargetPicker::create):
(WebMediaPlaybackTargetPicker::WebMediaPlaybackTargetPicker):
(WebMediaPlaybackTargetPicker::invalidate):
(WebMediaPlaybackTargetPicker::platformView const): New override.

* WebView/WebView.mm:
(-[WebView _devicePicker]): Pass view to WebMediaPlaybackTargetPicker factory.

Source/WTF:

* wtf/PlatformHave.h: Define HAVE_AVROUTEPICKERVIEW.

Tools:

* TestWebKitAPI/Tests/WebCore/cocoa/AVFoundationSoftLinkTest.mm:
(TestWebKitAPI::TEST): Test AVOutputContextOutputDevicesDidChangeNotification.
Don't check AVRouteDetectorMultipleRoutesDetectedDidChangeNotification on watchOS,
we don't use it there.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (264662 => 264663)


--- trunk/Source/WTF/ChangeLog	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WTF/ChangeLog	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,3 +1,13 @@
+2020-07-21  Eric Carlson  <eric.carl...@apple.com>
+
+        Use AVRoutePickerView when available for choosing AirPlay devices
+        https://bugs.webkit.org/show_bug.cgi?id=213497
+        <rdar://problem/58610662>
+
+        Reviewed by Jer Noble.
+
+        * wtf/PlatformHave.h: Define HAVE_AVROUTEPICKERVIEW.
+
 2020-07-20  Yusuke Suzuki  <ysuz...@apple.com>
 
         [ECMA-402] Implement Intl.DisplayNames

Modified: trunk/Source/WTF/wtf/PlatformHave.h (264662 => 264663)


--- trunk/Source/WTF/wtf/PlatformHave.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -691,3 +691,7 @@
     || (PLATFORM(APPLETV) && __TV_OS_VERSION_MIN_REQUIRED >= 140000)
 #define HAVE_LSDATABASECONTEXT 1
 #endif
+
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101600)
+#define HAVE_AVROUTEPICKERVIEW 1
+#endif

Modified: trunk/Source/WebCore/ChangeLog (264662 => 264663)


--- trunk/Source/WebCore/ChangeLog	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/ChangeLog	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,3 +1,101 @@
+2020-07-21  Eric Carlson  <eric.carl...@apple.com>
+
+        Use AVRoutePickerView when available for choosing AirPlay devices
+        https://bugs.webkit.org/show_bug.cgi?id=213497
+        <rdar://problem/58610662>
+
+        Reviewed by Jer Noble.
+
+        Use an AVRoutePickerView, the replacement for AVOutputDeviceMenuController, when
+        it is available to allow a user to pick an AirPlay device. To do this, create an 
+        AVPlaybackTargetPicker abstract base and create a concrete class from the 
+        AVOutputDeviceMenuController-specific code from MediaPlaybackTargetPickerMac, and
+        create a new concrete class using AVRoutePickerView.
+
+        Tested manually because these changes require an AirPlay device.
+
+        * Modules/mediasession/WebMediaSessionManager.cpp:
+        (WebCore::WebMediaSessionManager::showPlaybackTargetPicker): Pass the view to the
+        target picker.
+        * Modules/mediasession/WebMediaSessionManagerClient.h:
+
+        * Modules/remoteplayback/RemotePlayback.cpp:
+        (WebCore::RemotePlayback::playbackTargetPickerWasDismissed): Drive-by fix: return
+        early if there are no pending promises.
+
+        * SourcesCocoa.txt: Add new files.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+
+        * platform/graphics/MediaPlaybackTargetPicker.cpp:
+        (WebCore::MediaPlaybackTargetPicker::showPlaybackTargetPicker): Add new parameter.
+        * platform/graphics/MediaPlaybackTargetPicker.h:
+
+        * platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.h: Copied from Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h.
+        * platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.mm: Copied from Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm.
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::AVOutputDeviceMenuControllerTargetPicker):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::~AVOutputDeviceMenuControllerTargetPicker):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::devicePicker):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::availableDevicesDidChange):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::currentDeviceDidChange):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::showPlaybackTargetPicker):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::startingMonitoringPlaybackTargets):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::stopMonitoringPlaybackTargets):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::invalidatePlaybackTargets):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::externalOutputDeviceAvailable):
+        (WebCore::AVOutputDeviceMenuControllerTargetPicker::outputContext):
+        (-[WebAVOutputDeviceMenuControllerHelper initWithCallback:]):
+        (-[WebAVOutputDeviceMenuControllerHelper clearCallback]):
+        (-[WebAVOutputDeviceMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]):
+
+        * platform/graphics/avfoundation/objc/AVPlaybackTargetPicker.h: Added.
+        (WebCore::AVPlaybackTargetPicker::AVPlaybackTargetPicker):
+        (WebCore::AVPlaybackTargetPicker::client const):
+
+        * platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.h: Added.
+        * platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.mm: Added.
+        (WebCore::AVRoutePickerViewTargetPicker::isAvailable):
+        (WebCore::AVRoutePickerViewTargetPicker::AVRoutePickerViewTargetPicker):
+        (WebCore::AVRoutePickerViewTargetPicker::~AVRoutePickerViewTargetPicker):
+        (WebCore::AVRoutePickerViewTargetPicker::outputContextInternal):
+        (WebCore::AVRoutePickerViewTargetPicker::devicePicker):
+        (WebCore::AVRoutePickerViewTargetPicker::routeDetector):
+        (WebCore::AVRoutePickerViewTargetPicker::showPlaybackTargetPicker):
+        (WebCore::AVRoutePickerViewTargetPicker::startingMonitoringPlaybackTargets):
+        (WebCore::AVRoutePickerViewTargetPicker::stopMonitoringPlaybackTargets):
+        (WebCore::AVRoutePickerViewTargetPicker::externalOutputDeviceAvailable):
+        (WebCore::AVRoutePickerViewTargetPicker::outputContext):
+        (WebCore::AVRoutePickerViewTargetPicker::invalidatePlaybackTargets):
+        (WebCore::AVRoutePickerViewTargetPicker::availableDevicesDidChange):
+        (WebCore::AVRoutePickerViewTargetPicker::currentDeviceDidChange):
+        (WebCore::AVRoutePickerViewTargetPicker::devicePickerWasDismissed):
+        (-[WebAVRoutePickerViewHelper initWithCallback:]):
+        (-[WebAVRoutePickerViewHelper dealloc]):
+        (-[WebAVRoutePickerViewHelper clearCallback]):
+        (-[WebAVRoutePickerViewHelper routePickerViewDidEndPresentingRoutes:]):
+        (-[WebAVRoutePickerViewHelper notificationHandler:]):
+
+        * platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h:
+        * platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm:
+        (WebCore::MediaPlaybackTargetPickerMac::MediaPlaybackTargetPickerMac):
+        (WebCore::MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac):
+        (WebCore::MediaPlaybackTargetPickerMac::externalOutputDeviceAvailable):
+        (WebCore::MediaPlaybackTargetPickerMac::playbackTarget):
+        (WebCore::MediaPlaybackTargetPickerMac::routePicker):
+        (WebCore::MediaPlaybackTargetPickerMac::showPlaybackTargetPicker):
+        (WebCore::MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMac::invalidatePlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMac::pickerWasDismissed):
+        (WebCore::MediaPlaybackTargetPickerMac::availableDevicesChanged):
+        (WebCore::MediaPlaybackTargetPickerMac::currentDeviceChanged):
+        (WebCore::MediaPlaybackTargetPickerMac::devicePicker): Deleted.
+        (-[WebAVOutputDeviceMenuControllerHelper initWithCallback:]): Deleted.
+        (-[WebAVOutputDeviceMenuControllerHelper clearCallback]): Deleted.
+        (-[WebAVOutputDeviceMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]): Deleted.
+        * platform/mock/MediaPlaybackTargetPickerMock.cpp:
+        (WebCore::MediaPlaybackTargetPickerMock::showPlaybackTargetPicker):
+        * platform/mock/MediaPlaybackTargetPickerMock.h:
+
 2020-07-21  James Darpinian  <jdarpin...@chromium.org>
 
         webgl/2.0.0/conformance2/state/gl-object-get-calls.html results appears to show an out of bounds access bug.

Modified: trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp (264662 => 264663)


--- trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp	2020-07-21 17:46:28 UTC (rev 264663)
@@ -256,7 +256,7 @@
     ALWAYS_LOG_MEDIASESSIONMANAGER(__func__, m_clientState[index].get());
 
     bool hasActiveRoute = flagsAreSet(m_clientState[index]->flags, MediaProducer::IsPlayingToExternalDevice);
-    targetPicker().showPlaybackTargetPicker(FloatRect(rect), hasActiveRoute, useDarkAppearance);
+    targetPicker().showPlaybackTargetPicker(client.platformView(), FloatRect(rect), hasActiveRoute, useDarkAppearance);
 }
 
 void WebMediaSessionManager::clientStateDidChange(WebMediaSessionManagerClient& client, PlaybackTargetClientContextIdentifier contextId, MediaProducer::MediaStateFlags newFlags)

Modified: trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.h (264662 => 264663)


--- trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -31,6 +31,7 @@
 #include "MediaPlaybackTargetPicker.h"
 #include "MediaPlaybackTargetPickerMock.h"
 #include "MediaProducer.h"
+#include "PlatformView.h"
 #include "PlaybackTargetClientContextIdentifier.h"
 #include <wtf/Ref.h>
 #include <wtf/RefPtr.h>

Modified: trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManagerClient.h (264662 => 264663)


--- trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManagerClient.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManagerClient.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -29,6 +29,7 @@
 
 #include "MediaPlaybackTarget.h"
 #include "MediaProducer.h"
+#include "PlatformView.h"
 #include "PlaybackTargetClientContextIdentifier.h"
 #include <wtf/Ref.h>
 
@@ -43,6 +44,7 @@
     virtual void setShouldPlayToPlaybackTarget(PlaybackTargetClientContextIdentifier, bool) = 0;
     virtual void playbackTargetPickerWasDismissed(PlaybackTargetClientContextIdentifier) = 0;
     virtual bool alwaysOnLoggingAllowed() { return false; }
+    virtual PlatformView* platformView() const = 0;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.cpp (264662 => 264663)


--- trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.cpp	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/Modules/remoteplayback/RemotePlayback.cpp	2020-07-21 17:46:28 UTC (rev 264663)
@@ -324,6 +324,9 @@
 
 void RemotePlayback::playbackTargetPickerWasDismissed()
 {
+    if (m_promptPromises.isEmpty())
+        return;
+
     // 6.2.2 Prompt user for changing remote playback state [Ctd]
     // https://w3c.github.io/remote-playback/#stop-observing-remote-playback-devices-availability
     // W3C Editor's Draft 15 July 2016

Modified: trunk/Source/WebCore/PAL/ChangeLog (264662 => 264663)


--- trunk/Source/WebCore/PAL/ChangeLog	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/PAL/ChangeLog	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,3 +1,15 @@
+2020-07-21  Eric Carlson  <eric.carl...@apple.com>
+
+        Use AVRoutePickerView when available for choosing AirPlay devices
+        https://bugs.webkit.org/show_bug.cgi?id=213497
+        <rdar://problem/58610662>
+
+        Reviewed by Jer Noble.
+
+        * pal/cocoa/AVFoundationSoftLink.h:
+        * pal/cocoa/AVFoundationSoftLink.mm: Soft link AVRoutePickerView.
+        * pal/spi/cocoa/AVKitSPI.h: Declare AVRoutePickerView.
+
 2020-07-17  Truitt Savell  <tsav...@apple.com>
 
         Unreviewed, reverting r264477.

Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h (264662 => 264663)


--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -82,6 +82,10 @@
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVAudioRoutingArbiter)
 #endif
 
+#if HAVE(AVROUTEPICKERVIEW)
+SOFT_LINK_CLASS_FOR_HEADER(PAL, AVRoutePickerView)
+#endif
+
 #if !PLATFORM(WATCHOS)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVRouteDetector)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVVideoPerformanceMetrics)
@@ -291,8 +295,6 @@
 #define AVAudioSessionInterruptionTypeKey PAL::get_AVFoundation_AVAudioSessionInterruptionTypeKey()
 SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionInterruptionOptionKey, NSString *)
 #define AVAudioSessionInterruptionOptionKey PAL::get_AVFoundation_AVAudioSessionInterruptionOptionKey()
-SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVRouteDetectorMultipleRoutesDetectedDidChangeNotification, NSString *)
-#define AVRouteDetectorMultipleRoutesDetectedDidChangeNotification PAL::get_AVFoundation_AVRouteDetectorMultipleRoutesDetectedDidChangeNotification()
 SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionMediaServicesWereResetNotification, NSString *)
 #define AVAudioSessionMediaServicesWereResetNotification PAL::get_AVFoundation_AVAudioSessionMediaServicesWereResetNotification()
 SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionRouteChangeNotification, NSString *)
@@ -306,4 +308,14 @@
 #define AVCaptureSessionSetAuthorizedToUseCameraInMultipleForegroundAppLayout softLink_AVFoundation_AVCaptureSessionSetAuthorizedToUseCameraInMultipleForegroundAppLayout
 #endif // PLATFORM(IOS_FAMILY) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
 
+#if !PLATFORM(WATCHOS)
+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVRouteDetectorMultipleRoutesDetectedDidChangeNotification, NSString *)
+#define AVRouteDetectorMultipleRoutesDetectedDidChangeNotification PAL::get_AVFoundation_AVRouteDetectorMultipleRoutesDetectedDidChangeNotification()
+#endif // HAVE(WATCHOS)
+
+#if HAVE(AVROUTEPICKERVIEW)
+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVOutputContextOutputDevicesDidChangeNotification, NSString *)
+#define AVOutputContextOutputDevicesDidChangeNotification PAL::get_AVFoundation_AVOutputContextOutputDevicesDidChangeNotification()
+#endif // HAVE(AVROUTEPICKERVIEW)
+
 #endif // USE(AVFOUNDATION)

Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm (264662 => 264663)


--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -113,6 +113,10 @@
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVVideoPerformanceMetrics, PAL_EXPORT)
 #endif
 
+#if HAVE(AVROUTEPICKERVIEW)
+SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVRoutePickerView, PAL_EXPORT)
+#endif
+
 #if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
 SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVCaptureConnection, PAL_EXPORT)
 SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVCaptureDevice, PAL_EXPORT)
@@ -214,7 +218,6 @@
 SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVCaptureSessionInterruptionReasonKey, NSString *, PAL_EXPORT)
 SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVCaptureSessionRuntimeErrorNotification, NSString *, PAL_EXPORT)
 SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVCaptureSessionWasInterruptedNotification, NSString *, PAL_EXPORT)
-SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVRouteDetectorMultipleRoutesDetectedDidChangeNotification, NSString *, PAL_EXPORT)
 SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetBoundNetworkInterfaceName, NSString *, PAL_EXPORT)
 SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetClientBundleIdentifierKey, NSString *, PAL_EXPORT)
 SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVAudioSessionRouteChangeNotification, NSString *, PAL_EXPORT)
@@ -228,4 +231,12 @@
 SOFT_LINK_FUNCTION_FOR_SOURCE(PAL, AVFoundation, AVCaptureSessionSetAuthorizedToUseCameraInMultipleForegroundAppLayout, void, (AVCaptureSession *session), (session))
 #endif // PLATFORM(IOS_FAMILY) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
 
+#if !PLATFORM(WATCHOS)
+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVRouteDetectorMultipleRoutesDetectedDidChangeNotification, NSString *, PAL_EXPORT)
+#endif // HAVE(WATCHOS)
+
+#if HAVE(AVROUTEPICKERVIEW)
+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVOutputContextOutputDevicesDidChangeNotification, NSString *, PAL_EXPORT)
+#endif // HAVE(AVROUTEPICKERVIEW)
+
 #endif // USE(AVFOUNDATION)

Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h (264662 => 264663)


--- trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -74,6 +74,7 @@
 @interface AVOutputContext : NSObject <NSSecureCoding>
 @property (nonatomic, readonly) NSString *deviceName;
 + (instancetype)outputContext;
++ (instancetype)iTunesAudioContext;
 + (nullable AVOutputContext *)sharedAudioPresentationOutputContext;
 + (nullable AVOutputContext *)outputContextForID:(NSString *)ID;
 @property (readonly) BOOL supportsMultipleOutputDevices;

Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/AVKitSPI.h (264662 => 264663)


--- trunk/Source/WebCore/PAL/pal/spi/cocoa/AVKitSPI.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/AVKitSPI.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -228,7 +228,6 @@
 #endif // PLATFORM(MAC)
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
-
 #if USE(APPLE_INTERNAL_SDK)
 
 #import <AVKit/AVOutputDeviceMenuController.h>
@@ -256,7 +255,6 @@
 NS_ASSUME_NONNULL_END
 
 #endif // USE(APPLE_INTERNAL_SDK)
-
 #endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
 
 NS_ASSUME_NONNULL_BEGIN
@@ -358,3 +356,35 @@
 #endif
 
 #endif // PLATFORM(MAC) && ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && HAVE(AVROUTEPICKERVIEW)
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <AVKit/AVRoutePickerView_Private.h>
+#import <AVKit/AVRoutePickerView_WebKitOnly.h>
+
+#else
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol AVRoutePickerViewDelegate;
+
+@interface AVRoutePickerView : NSView
+
+- (void)showRoutePickingControlsForOutputContext:(AVOutputContext *)outputContext relativeToRect:(NSRect)positioningRect ofView:(NSView *)positioningView;
+
+@property (nonatomic, nullable, weak) id<AVRoutePickerViewDelegate> delegate;
+@property (nonatomic) BOOL routeListAlwaysHasDarkAppearance;
+
+@end
+
+@protocol AVRoutePickerViewDelegate <NSObject>
+@optional
+- (void)routePickerViewWillBeginPresentingRoutes:(AVRoutePickerView *)routePickerView;
+- (void)routePickerViewDidEndPresentingRoutes:(AVRoutePickerView *)routePickerView;
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // USE(APPLE_INTERNAL_SDK)
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && HAVE(AVROUTEPICKERVIEW)

Modified: trunk/Source/WebCore/SourcesCocoa.txt (264662 => 264663)


--- trunk/Source/WebCore/SourcesCocoa.txt	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2020-07-21 17:46:28 UTC (rev 264663)
@@ -274,6 +274,8 @@
 platform/graphics/avfoundation/WebMediaSessionManagerMac.cpp @no-unify
 platform/graphics/avfoundation/objc/AVAssetMIMETypeCache.mm @no-unify
 platform/graphics/avfoundation/objc/AVAssetTrackUtilities.mm @no-unify
+platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.mm @no-unify
+platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.mm @no-unify
 platform/graphics/avfoundation/objc/AVStreamDataParserMIMETypeCache.mm @no-unify
 platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm @no-unify
 platform/graphics/avfoundation/objc/AudioTrackPrivateMediaSourceAVFObjC.cpp @no-unify

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (264662 => 264663)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-07-21 17:46:28 UTC (rev 264663)
@@ -118,6 +118,7 @@
 		073794EC19EE341E00E5A045 /* JSRTCIceServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 073794EA19EE341E00E5A045 /* JSRTCIceServer.h */; };
 		073794FA19F5864E00E5A045 /* RTCDataChannelHandlerMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 073794F419F5864E00E5A045 /* RTCDataChannelHandlerMock.h */; };
 		073794FE19F5864E00E5A045 /* RTCNotifiersMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 073794F819F5864E00E5A045 /* RTCNotifiersMock.h */; };
+		0738E5EC2499839000DA101C /* AVOutputDeviceMenuControllerTargetPicker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0738E5EA249968AD00DA101C /* AVOutputDeviceMenuControllerTargetPicker.mm */; };
 		073A15542177A42600EA08F2 /* RemoteVideoSample.h in Headers */ = {isa = PBXBuildFile; fileRef = 073A15532177A39A00EA08F2 /* RemoteVideoSample.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		073B87671E4385AC0071C0EC /* AudioSampleBufferList.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87631E43859D0071C0EC /* AudioSampleBufferList.h */; };
 		073B87691E4385AC0071C0EC /* AudioSampleDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87651E43859D0071C0EC /* AudioSampleDataSource.h */; };
@@ -204,6 +205,7 @@
 		07C046CB1E426413007201E7 /* AudioStreamDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87561E40DCE50071C0EC /* AudioStreamDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07C1C0E21BFB600100BD2256 /* MediaTrackSupportedConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C1C0E01BFB600100BD2256 /* MediaTrackSupportedConstraints.h */; };
 		07C1C0E51BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C1C0E41BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		07CB9E72249C36B200A69489 /* AVRoutePickerViewTargetPicker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07CB9E6F249C226C00A69489 /* AVRoutePickerViewTargetPicker.mm */; };
 		07CE77D516712A6A00C55A47 /* InbandTextTrackPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07D12F5C23DE543F0080997D /* ISOVTTCue.h in Headers */ = {isa = PBXBuildFile; fileRef = CD871C651FB52B6700F0B965 /* ISOVTTCue.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07D637401BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -5573,6 +5575,9 @@
 		073794F419F5864E00E5A045 /* RTCDataChannelHandlerMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCDataChannelHandlerMock.h; sourceTree = "<group>"; };
 		073794F719F5864E00E5A045 /* RTCNotifiersMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCNotifiersMock.cpp; sourceTree = "<group>"; };
 		073794F819F5864E00E5A045 /* RTCNotifiersMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCNotifiersMock.h; sourceTree = "<group>"; };
+		0738E5E8249968AC00DA101C /* AVOutputDeviceMenuControllerTargetPicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AVOutputDeviceMenuControllerTargetPicker.h; sourceTree = "<group>"; };
+		0738E5EA249968AD00DA101C /* AVOutputDeviceMenuControllerTargetPicker.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AVOutputDeviceMenuControllerTargetPicker.mm; sourceTree = "<group>"; };
+		0738E5EB2499690900DA101C /* AVPlaybackTargetPicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AVPlaybackTargetPicker.h; sourceTree = "<group>"; };
 		073A15512177A39800EA08F2 /* RemoteVideoSample.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteVideoSample.cpp; sourceTree = "<group>"; };
 		073A15532177A39A00EA08F2 /* RemoteVideoSample.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteVideoSample.h; sourceTree = "<group>"; };
 		073B87561E40DCE50071C0EC /* AudioStreamDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioStreamDescription.h; sourceTree = "<group>"; };
@@ -5687,6 +5692,8 @@
 		07C1C0E41BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeMediaSourceSupportedConstraints.h; sourceTree = "<group>"; };
 		07C8AD111D073D630087C5CE /* AVAssetMIMETypeCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AVAssetMIMETypeCache.mm; sourceTree = "<group>"; };
 		07C8AD121D073D630087C5CE /* AVAssetMIMETypeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVAssetMIMETypeCache.h; sourceTree = "<group>"; };
+		07CB9E6F249C226C00A69489 /* AVRoutePickerViewTargetPicker.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AVRoutePickerViewTargetPicker.mm; sourceTree = "<group>"; };
+		07CB9E71249C226C00A69489 /* AVRoutePickerViewTargetPicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AVRoutePickerViewTargetPicker.h; sourceTree = "<group>"; };
 		07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateClient.h; sourceTree = "<group>"; };
 		07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAudioSourceProviderAVFObjC.h; sourceTree = "<group>"; };
 		07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAudioSourceProviderAVFObjC.mm; sourceTree = "<group>"; };
@@ -27359,6 +27366,11 @@
 				07C8AD111D073D630087C5CE /* AVAssetMIMETypeCache.mm */,
 				CDECA8991EDF447D00DCB08B /* AVAssetTrackUtilities.h */,
 				CDECA8981EDF447D00DCB08B /* AVAssetTrackUtilities.mm */,
+				0738E5E8249968AC00DA101C /* AVOutputDeviceMenuControllerTargetPicker.h */,
+				0738E5EA249968AD00DA101C /* AVOutputDeviceMenuControllerTargetPicker.mm */,
+				0738E5EB2499690900DA101C /* AVPlaybackTargetPicker.h */,
+				07CB9E71249C226C00A69489 /* AVRoutePickerViewTargetPicker.h */,
+				07CB9E6F249C226C00A69489 /* AVRoutePickerViewTargetPicker.mm */,
 				CD11B3DF227CAAA90023AFC7 /* AVStreamDataParserMIMETypeCache.h */,
 				CD11B3E0227CAAA90023AFC7 /* AVStreamDataParserMIMETypeCache.mm */,
 				CD78A2EE1F75648600DE371B /* CDMInstanceFairPlayStreamingAVFObjC.h */,
@@ -34499,6 +34511,8 @@
 				CDECA89A1EDF447D00DCB08B /* AVAssetTrackUtilities.mm in Sources */,
 				CDC675221EAEA9B700727C84 /* AVAudioSessionCaptureDeviceManager.mm in Sources */,
 				070363E3181A1CDC00C074A5 /* AVCaptureDeviceManager.mm in Sources */,
+				0738E5EC2499839000DA101C /* AVOutputDeviceMenuControllerTargetPicker.mm in Sources */,
+				07CB9E72249C36B200A69489 /* AVRoutePickerViewTargetPicker.mm in Sources */,
 				CD11B3E1227CE6F30023AFC7 /* AVStreamDataParserMIMETypeCache.mm in Sources */,
 				CD336F6117F9F64700DDDCD0 /* AVTrackPrivateAVFObjCImpl.mm in Sources */,
 				070363E7181A1CDC00C074A5 /* AVVideoCaptureSource.mm in Sources */,

Modified: trunk/Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.cpp (264662 => 264663)


--- trunk/Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.cpp	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.cpp	2020-07-21 17:46:28 UTC (rev 264663)
@@ -73,7 +73,7 @@
     m_pendingActionTimer.startOneShot(pendingActionInterval);
 }
 
-void MediaPlaybackTargetPicker::showPlaybackTargetPicker(const FloatRect&, bool, bool)
+void MediaPlaybackTargetPicker::showPlaybackTargetPicker(PlatformView*, const FloatRect&, bool, bool)
 {
     ASSERT_NOT_REACHED();
 }

Modified: trunk/Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.h (264662 => 264663)


--- trunk/Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -28,6 +28,7 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 
+#include "PlatformView.h"
 #include <wtf/Ref.h>
 #include <wtf/RunLoop.h>
 
@@ -52,7 +53,7 @@
 
     virtual ~MediaPlaybackTargetPicker();
 
-    virtual void showPlaybackTargetPicker(const FloatRect&, bool checkActiveRoute, bool useDarkAppearance);
+    virtual void showPlaybackTargetPicker(PlatformView*, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance);
     virtual void startingMonitoringPlaybackTargets();
     virtual void stopMonitoringPlaybackTargets();
     virtual void invalidatePlaybackTargets();

Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.h (from rev 264662, trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h) (0 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
+
+#include "AVPlaybackTargetPicker.h"
+
+OBJC_CLASS AVOutputDeviceMenuController;
+OBJC_CLASS WebAVOutputDeviceMenuControllerHelper;
+
+namespace WebCore {
+
+class AVOutputDeviceMenuControllerTargetPicker final : public AVPlaybackTargetPicker {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(AVOutputDeviceMenuControllerTargetPicker);
+public:
+    explicit AVOutputDeviceMenuControllerTargetPicker(AVPlaybackTargetPicker::Client&);
+    virtual ~AVOutputDeviceMenuControllerTargetPicker();
+
+    void availableDevicesDidChange();
+    void currentDeviceDidChange();
+
+private:
+    void showPlaybackTargetPicker(NSView *, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) final;
+    void startingMonitoringPlaybackTargets() final;
+    void stopMonitoringPlaybackTargets() final;
+    void invalidatePlaybackTargets() final;
+    bool externalOutputDeviceAvailable() final;
+    AVOutputContext* outputContext() final;
+
+    AVOutputDeviceMenuController *devicePicker();
+
+    RetainPtr<AVOutputDeviceMenuController> m_outputDeviceMenuController;
+    RetainPtr<WebAVOutputDeviceMenuControllerHelper> m_outputDeviceMenuControllerDelegate;
+    bool m_showingMenu { false };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)

Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.mm (from rev 264662, trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm) (0 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVOutputDeviceMenuControllerTargetPicker.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "AVOutputDeviceMenuControllerTargetPicker.h"
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
+
+#import "Logging.h"
+#import <WebCore/FloatRect.h>
+#import <objc/runtime.h>
+#import <pal/spi/cocoa/AVFoundationSPI.h>
+#import <pal/spi/cocoa/AVKitSPI.h>
+#import <wtf/MainThread.h>
+
+#import <pal/cf/CoreMediaSoftLink.h>
+#import <pal/cocoa/AVFoundationSoftLink.h>
+
+SOFTLINK_AVKIT_FRAMEWORK()
+SOFT_LINK_CLASS_OPTIONAL(AVKit, AVOutputDeviceMenuController)
+
+using namespace WebCore;
+
+static NSString *externalOutputDeviceAvailableKeyName = @"externalOutputDeviceAvailable";
+static NSString *externalOutputDevicePickedKeyName = @"externalOutputDevicePicked";
+
+@interface WebAVOutputDeviceMenuControllerHelper : NSObject {
+    WeakPtr<AVOutputDeviceMenuControllerTargetPicker> m_callback;
+}
+
+- (instancetype)initWithCallback:(WeakPtr<AVOutputDeviceMenuControllerTargetPicker>&&)callback;
+- (void)clearCallback;
+- (void)observeValueForKeyPath:(id)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
+@end
+
+namespace WebCore {
+
+AVOutputDeviceMenuControllerTargetPicker::AVOutputDeviceMenuControllerTargetPicker(AVPlaybackTargetPicker::Client& client)
+    : AVPlaybackTargetPicker(client)
+    , m_outputDeviceMenuControllerDelegate(adoptNS([[WebAVOutputDeviceMenuControllerHelper alloc] initWithCallback:makeWeakPtr(*this)]))
+{
+}
+
+AVOutputDeviceMenuControllerTargetPicker::~AVOutputDeviceMenuControllerTargetPicker()
+{
+    [m_outputDeviceMenuControllerDelegate clearCallback];
+}
+
+AVOutputDeviceMenuController *AVOutputDeviceMenuControllerTargetPicker::devicePicker()
+{
+    if (!getAVOutputDeviceMenuControllerClass())
+        return nullptr;
+
+    if (!m_outputDeviceMenuController) {
+        RetainPtr<AVOutputContext> context = adoptNS([PAL::allocAVOutputContextInstance() init]);
+        m_outputDeviceMenuController = adoptNS([allocAVOutputDeviceMenuControllerInstance() initWithOutputContext:context.get()]);
+
+        [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDeviceAvailableKeyName options:NSKeyValueObservingOptionNew context:nullptr];
+        [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDevicePickedKeyName options:NSKeyValueObservingOptionNew context:nullptr];
+
+        ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+        if (m_outputDeviceMenuController.get().externalOutputDeviceAvailable)
+            availableDevicesDidChange();
+        ALLOW_DEPRECATED_DECLARATIONS_END
+    }
+
+    return m_outputDeviceMenuController.get();
+}
+
+void AVOutputDeviceMenuControllerTargetPicker::availableDevicesDidChange()
+{
+    if (client())
+        client()->availableDevicesChanged();
+}
+
+void AVOutputDeviceMenuControllerTargetPicker::currentDeviceDidChange()
+{
+    if (client())
+        client()->currentDeviceChanged();
+}
+
+void AVOutputDeviceMenuControllerTargetPicker::showPlaybackTargetPicker(NSView *, const FloatRect& location, bool hasActiveRoute, bool useDarkAppearance)
+{
+    if (!client() || m_showingMenu)
+        return;
+
+    m_showingMenu = true;
+
+    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    bool targetSelected = [devicePicker() showMenuForRect:location appearanceName:(useDarkAppearance ? NSAppearanceNameVibrantDark : NSAppearanceNameVibrantLight) allowReselectionOfSelectedOutputDevice:!hasActiveRoute];
+    ALLOW_DEPRECATED_DECLARATIONS_END
+
+    if (!client())
+        return;
+
+    if (targetSelected != hasActiveRoute)
+        currentDeviceDidChange();
+    else if (!targetSelected && !hasActiveRoute)
+        client()->pickerWasDismissed();
+
+    m_showingMenu = false;
+}
+
+void AVOutputDeviceMenuControllerTargetPicker::startingMonitoringPlaybackTargets()
+{
+    devicePicker();
+}
+
+void AVOutputDeviceMenuControllerTargetPicker::stopMonitoringPlaybackTargets()
+{
+    // Nothing to do, AirPlay takes care of this automatically.
+}
+
+void AVOutputDeviceMenuControllerTargetPicker::invalidatePlaybackTargets()
+{
+    if (m_outputDeviceMenuController) {
+        [m_outputDeviceMenuController removeObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDeviceAvailableKeyName];
+        [m_outputDeviceMenuController removeObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDevicePickedKeyName];
+        m_outputDeviceMenuController = nullptr;
+    }
+    currentDeviceDidChange();
+}
+
+bool AVOutputDeviceMenuControllerTargetPicker::externalOutputDeviceAvailable()
+{
+    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    return devicePicker().externalOutputDeviceAvailable;
+    ALLOW_DEPRECATED_DECLARATIONS_END
+}
+
+AVOutputContext * AVOutputDeviceMenuControllerTargetPicker::outputContext()
+{
+    return m_outputDeviceMenuController ? [m_outputDeviceMenuController.get() outputContext] : nullptr;
+}
+
+} // namespace WebCore
+
+@implementation WebAVOutputDeviceMenuControllerHelper
+- (instancetype)initWithCallback:(WeakPtr<AVOutputDeviceMenuControllerTargetPicker>&&)callback
+{
+    if (!(self = [super init]))
+        return nil;
+
+    m_callback = WTFMove(callback);
+
+    return self;
+}
+
+- (void)clearCallback
+{
+    m_callback = nil;
+}
+
+- (void)observeValueForKeyPath:(id)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(change);
+    UNUSED_PARAM(context);
+
+    if (!m_callback)
+        return;
+
+    if (![keyPath isEqualToString:externalOutputDeviceAvailableKeyName] && ![keyPath isEqualToString:externalOutputDevicePickedKeyName])
+        return;
+
+    callOnMainThread([self, protectedSelf = retainPtr(self), keyPath = retainPtr(keyPath)] {
+        if (!m_callback)
+            return;
+
+        if ([keyPath isEqualToString:externalOutputDeviceAvailableKeyName])
+            m_callback->availableDevicesDidChange();
+        else if ([keyPath isEqualToString:externalOutputDevicePickedKeyName])
+            m_callback->currentDeviceDidChange();
+    });
+}
+@end
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)

Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVPlaybackTargetPicker.h (from rev 264662, trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h) (0 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVPlaybackTargetPicker.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVPlaybackTargetPicker.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
+
+#include <wtf/WeakPtr.h>
+
+OBJC_CLASS AVOutputContext;
+OBJC_CLASS NSView;
+
+namespace WebCore {
+
+class FloatRect;
+
+class AVPlaybackTargetPicker : public CanMakeWeakPtr<AVPlaybackTargetPicker> {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(AVPlaybackTargetPicker);
+public:
+    class Client : public CanMakeWeakPtr<Client> {
+    protected:
+        virtual ~Client() = default;
+
+    public:
+        virtual void pickerWasDismissed() = 0;
+        virtual void availableDevicesChanged() = 0;
+        virtual void currentDeviceChanged() = 0;
+    };
+
+    explicit AVPlaybackTargetPicker(Client& client)
+        : m_client(makeWeakPtr(&client))
+    {
+    }
+    virtual ~AVPlaybackTargetPicker() = default;
+
+    virtual void showPlaybackTargetPicker(NSView *, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) = 0;
+    virtual void startingMonitoringPlaybackTargets() = 0;
+    virtual void stopMonitoringPlaybackTargets() = 0;
+    virtual void invalidatePlaybackTargets() = 0;
+    virtual bool externalOutputDeviceAvailable() = 0;
+
+    virtual AVOutputContext* outputContext() = 0;
+
+    WeakPtr<AVPlaybackTargetPicker::Client> client() const { return m_client; }
+
+private:
+    WeakPtr<AVPlaybackTargetPicker::Client> m_client;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)

Copied: trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.h (from rev 264662, trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h) (0 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
+
+#include "AVPlaybackTargetPicker.h"
+
+OBJC_CLASS AVRouteDetector;
+OBJC_CLASS AVRoutePickerView;
+OBJC_CLASS WebAVRoutePickerViewHelper;
+
+namespace WebCore {
+
+class AVRoutePickerViewTargetPicker final : public AVPlaybackTargetPicker {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(AVRoutePickerViewTargetPicker);
+public:
+    explicit AVRoutePickerViewTargetPicker(AVPlaybackTargetPicker::Client&);
+    virtual ~AVRoutePickerViewTargetPicker();
+    
+    static bool isAvailable();
+
+    void availableDevicesDidChange();
+    void currentDeviceDidChange();
+    void devicePickerWasDismissed();
+
+private:
+    void showPlaybackTargetPicker(NSView *, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) final;
+    void startingMonitoringPlaybackTargets() final;
+    void stopMonitoringPlaybackTargets() final;
+    void invalidatePlaybackTargets() final;
+    bool externalOutputDeviceAvailable() final;
+    AVOutputContext *outputContext() final;
+
+    AVRoutePickerView *devicePicker();
+    AVRouteDetector *routeDetector();
+    AVOutputContext * outputContextInternal();
+    bool hasActiveRoute() const;
+
+    RetainPtr<AVRouteDetector> m_routeDetector;
+    RetainPtr<AVRoutePickerView> m_routePickerView;
+    RetainPtr<AVOutputContext> m_outputContext;
+    RetainPtr<WebAVRoutePickerViewHelper> m_routePickerViewDelegate;
+    bool m_hadActiveRoute { false };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)

Added: trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.mm (0 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/AVRoutePickerViewTargetPicker.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "AVRoutePickerViewTargetPicker.h"
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && HAVE(AVROUTEPICKERVIEW)
+
+#import "Logging.h"
+#import <AVFoundation/AVRouteDetector.h>
+#import <WebCore/FloatRect.h>
+#import <pal/spi/cocoa/AVFoundationSPI.h>
+#import <pal/spi/cocoa/AVKitSPI.h>
+#import <wtf/MainThread.h>
+
+#import <pal/cf/CoreMediaSoftLink.h>
+#import <pal/cocoa/AVFoundationSoftLink.h>
+
+SOFTLINK_AVKIT_FRAMEWORK()
+SOFT_LINK_CLASS_OPTIONAL(AVKit, AVRoutePickerView)
+
+using namespace WebCore;
+
+@interface WebAVRoutePickerViewHelper : NSObject <AVRoutePickerViewDelegate> {
+    WeakPtr<AVRoutePickerViewTargetPicker> m_callback;
+}
+
+- (instancetype)initWithCallback:(WeakPtr<AVRoutePickerViewTargetPicker>&&)callback;
+- (void)clearCallback;
+- (void)notificationHandler:(NSNotification *)notification;
+- (void)routePickerViewDidEndPresentingRoutes:(AVRoutePickerView *)routePickerView;
+@end
+
+namespace WebCore {
+
+bool AVRoutePickerViewTargetPicker::isAvailable()
+{
+    static bool available;
+    static std::once_flag flag;
+    std::call_once(flag, [] () {
+        if (!PAL::getAVRoutePickerViewClass())
+            return;
+
+        if (auto picker = adoptNS([allocAVRoutePickerViewInstance() init]))
+            available = [picker respondsToSelector:@selector(showRoutePickingControlsForOutputContext:relativeToRect:ofView:)];
+    });
+
+    return available;
+}
+
+AVRoutePickerViewTargetPicker::AVRoutePickerViewTargetPicker(AVPlaybackTargetPicker::Client& client)
+    : AVPlaybackTargetPicker(client)
+    , m_routePickerViewDelegate(adoptNS([[WebAVRoutePickerViewHelper alloc] initWithCallback:makeWeakPtr(*this)]))
+{
+    ASSERT(isAvailable());
+}
+
+AVRoutePickerViewTargetPicker::~AVRoutePickerViewTargetPicker()
+{
+    [m_routePickerViewDelegate clearCallback];
+}
+
+AVOutputContext * AVRoutePickerViewTargetPicker::outputContextInternal()
+{
+    if (!m_outputContext) {
+        m_outputContext = [PAL::getAVOutputContextClass() iTunesAudioContext];
+        ASSERT(m_outputContext);
+        if (m_outputContext)
+            [[NSNotificationCenter defaultCenter] addObserver:m_routePickerViewDelegate.get() selector:@selector(notificationHandler:) name:PAL::get_AVFoundation_AVOutputContextOutputDevicesDidChangeNotification() object:m_outputContext.get()];
+    }
+
+    return m_outputContext.get();
+}
+
+AVRoutePickerView *AVRoutePickerViewTargetPicker::devicePicker()
+{
+    if (!m_routePickerView) {
+        m_routePickerView = adoptNS([allocAVRoutePickerViewInstance() init]);
+        [m_routePickerView setDelegate:m_routePickerViewDelegate.get()];
+    }
+
+    return m_routePickerView.get();
+}
+
+AVRouteDetector *AVRoutePickerViewTargetPicker::routeDetector()
+{
+    if (!m_routeDetector) {
+        m_routeDetector = adoptNS([PAL::allocAVRouteDetectorInstance() init]);
+        [[NSNotificationCenter defaultCenter] addObserver:m_routePickerViewDelegate.get() selector:@selector(notificationHandler:) name:PAL::get_AVFoundation_AVRouteDetectorMultipleRoutesDetectedDidChangeNotification() object:m_routeDetector.get()];
+        if ([m_routeDetector multipleRoutesDetected])
+            availableDevicesDidChange();
+    }
+
+    return m_routeDetector.get();
+}
+
+void AVRoutePickerViewTargetPicker::showPlaybackTargetPicker(NSView *view, const FloatRect& rectInScreenCoordinates, bool hasActiveRoute, bool useDarkAppearance)
+{
+    if (!client())
+        return;
+
+    auto *picker = devicePicker();
+    if (useDarkAppearance)
+        picker.routeListAlwaysHasDarkAppearance = YES;
+
+    m_hadActiveRoute = hasActiveRoute;
+
+    auto rectInWindowCoordinates = [view.window convertRectFromScreen:NSMakeRect(rectInScreenCoordinates.x(), rectInScreenCoordinates.y(), 1.0, 1.0)];
+    auto rectInViewCoordinates = [view convertRect:rectInWindowCoordinates fromView:view];
+    [picker showRoutePickingControlsForOutputContext:outputContextInternal() relativeToRect:rectInViewCoordinates ofView:view];
+}
+
+void AVRoutePickerViewTargetPicker::startingMonitoringPlaybackTargets()
+{
+    routeDetector().routeDetectionEnabled = YES;
+}
+
+void AVRoutePickerViewTargetPicker::stopMonitoringPlaybackTargets()
+{
+    if (m_routeDetector)
+        [m_routeDetector setRouteDetectionEnabled:NO];
+}
+
+bool AVRoutePickerViewTargetPicker::externalOutputDeviceAvailable()
+{
+    return routeDetector().multipleRoutesDetected;
+}
+
+AVOutputContext * AVRoutePickerViewTargetPicker::outputContext()
+{
+    return m_outputContext.get();
+}
+
+void AVRoutePickerViewTargetPicker::invalidatePlaybackTargets()
+{
+    if (m_routeDetector) {
+        [[NSNotificationCenter defaultCenter] removeObserver:m_routePickerViewDelegate.get() name:PAL::get_AVFoundation_AVRouteDetectorMultipleRoutesDetectedDidChangeNotification() object:m_routeDetector.get()];
+        [m_routeDetector setRouteDetectionEnabled:NO];
+        m_routePickerView = nullptr;
+    }
+
+    if (m_outputContext) {
+        [[NSNotificationCenter defaultCenter] removeObserver:m_routePickerViewDelegate.get() name:PAL::get_AVFoundation_AVOutputContextOutputDevicesDidChangeNotification() object:m_outputContext.get()];
+        m_outputContext = nullptr;
+    }
+
+    if (m_routePickerView) {
+        [m_routePickerView setDelegate:nil];
+        m_routePickerView = nullptr;
+    }
+    currentDeviceDidChange();
+}
+void AVRoutePickerViewTargetPicker::availableDevicesDidChange()
+{
+    if (client())
+        client()->availableDevicesChanged();
+}
+
+bool AVRoutePickerViewTargetPicker::hasActiveRoute() const
+{
+    if (!m_outputContext)
+        return false;
+
+    if ([m_outputContext respondsToSelector:@selector(supportsMultipleOutputDevices)] && [m_outputContext respondsToSelector:@selector(outputDevices)]&& [m_outputContext supportsMultipleOutputDevices]) {
+        for (AVOutputDevice *outputDevice in [m_outputContext outputDevices]) {
+            if (outputDevice.deviceFeatures & (AVOutputDeviceFeatureVideo | AVOutputDeviceFeatureAudio))
+                return true;
+        }
+
+        return false;
+    }
+
+    if ([m_outputContext respondsToSelector:@selector(outputDevice)]) {
+        if (auto *outputDevice = [m_outputContext outputDevice])
+            return outputDevice.deviceFeatures & (AVOutputDeviceFeatureVideo | AVOutputDeviceFeatureAudio);
+    }
+
+    return [m_outputContext deviceName];
+}
+
+void AVRoutePickerViewTargetPicker::currentDeviceDidChange()
+{
+    auto haveActiveRoute = hasActiveRoute();
+    if (!client() || m_hadActiveRoute == haveActiveRoute)
+        return;
+
+    m_hadActiveRoute = haveActiveRoute;
+    client()->currentDeviceChanged();
+}
+
+void AVRoutePickerViewTargetPicker::devicePickerWasDismissed()
+{
+    if (!client())
+        return;
+    
+    client()->pickerWasDismissed();
+    currentDeviceDidChange();
+}
+
+} // namespace WebCore
+
+@implementation WebAVRoutePickerViewHelper
+- (instancetype)initWithCallback:(WeakPtr<AVRoutePickerViewTargetPicker>&&)callback
+{
+    if (!(self = [super init]))
+        return nil;
+
+    m_callback = WTFMove(callback);
+
+    return self;
+}
+
+- (void)clearCallback
+{
+    m_callback = nil;
+}
+
+- (void)routePickerViewDidEndPresentingRoutes:(AVRoutePickerView *)routePickerView
+{
+    UNUSED_PARAM(routePickerView);
+
+    if (!m_callback)
+        return;
+
+    callOnMainThread([self, protectedSelf = retainPtr(self)] {
+        if (!m_callback)
+            return;
+
+        m_callback->devicePickerWasDismissed();
+    });
+}
+
+- (void)notificationHandler:(NSNotification *)notification
+{
+    UNUSED_PARAM(notification);
+
+    if (!m_callback)
+        return;
+
+    callOnMainThread([self, protectedSelf = retainPtr(self), notification = retainPtr(notification)] {
+        if (!m_callback)
+            return;
+
+        if ([[notification name] isEqualToString:PAL::get_AVFoundation_AVOutputContextOutputDevicesDidChangeNotification()])
+            m_callback->currentDeviceDidChange();
+        else if ([[notification name] isEqualToString:PAL::get_AVFoundation_AVRouteDetectorMultipleRoutesDetectedDidChangeNotification()])
+            m_callback->availableDevicesDidChange();
+    });
+}
+
+@end
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h (264662 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,36 +28,36 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
 
+#include "AVPlaybackTargetPicker.h"
 #include "MediaPlaybackTargetPicker.h"
 #include <wtf/RetainPtr.h>
 
-OBJC_CLASS AVOutputDeviceMenuController;
-OBJC_CLASS WebAVOutputDeviceMenuControllerHelper;
-
 namespace WebCore {
 
-class MediaPlaybackTargetPickerMac final : public MediaPlaybackTargetPicker {
+class MediaPlaybackTargetPickerMac final : public MediaPlaybackTargetPicker, public AVPlaybackTargetPicker::Client {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(MediaPlaybackTargetPickerMac);
 public:
     explicit MediaPlaybackTargetPickerMac(MediaPlaybackTargetPicker::Client&);
-
     virtual ~MediaPlaybackTargetPickerMac();
 
-    void showPlaybackTargetPicker(const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) override;
-    void startingMonitoringPlaybackTargets() override;
-    void stopMonitoringPlaybackTargets() override;
-    void invalidatePlaybackTargets() override;
+    void showPlaybackTargetPicker(PlatformView*, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) final;
+    void startingMonitoringPlaybackTargets() final;
+    void stopMonitoringPlaybackTargets() final;
+    void invalidatePlaybackTargets() final;
 
 private:
-    bool externalOutputDeviceAvailable() override;
-    Ref<MediaPlaybackTarget> playbackTarget() override;
+    bool externalOutputDeviceAvailable() final;
+    Ref<MediaPlaybackTarget> playbackTarget() final;
 
-    AVOutputDeviceMenuController *devicePicker();
+    // AVPlaybackTargetPicker::Client
+    void pickerWasDismissed() final;
+    void availableDevicesChanged() final;
+    void currentDeviceChanged() final;
 
-    RetainPtr<AVOutputDeviceMenuController> m_outputDeviceMenuController;
-    RetainPtr<WebAVOutputDeviceMenuControllerHelper> m_outputDeviceMenuControllerDelegate;
-    bool m_showingMenu { false };
+    AVPlaybackTargetPicker& routePicker();
+
+    std::unique_ptr<AVPlaybackTargetPicker> m_routePicker;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm (264662 => 264663)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
 
+#import "AVOutputDeviceMenuControllerTargetPicker.h"
 #import "Logging.h"
 #import <WebCore/FloatRect.h>
 #import <WebCore/MediaPlaybackTargetCocoa.h>
@@ -36,6 +37,10 @@
 #import <pal/spi/cocoa/AVKitSPI.h>
 #import <wtf/MainThread.h>
 
+#if HAVE(AVROUTEPICKERVIEW)
+#import "AVRoutePickerViewTargetPicker.h"
+#endif
+
 #import <pal/cf/CoreMediaSoftLink.h>
 #import <pal/cocoa/AVFoundationSoftLink.h>
 
@@ -44,23 +49,10 @@
 
 using namespace WebCore;
 
-static NSString *externalOutputDeviceAvailableKeyName = @"externalOutputDeviceAvailable";
-static NSString *externalOutputDevicePickedKeyName = @"externalOutputDevicePicked";
-
-@interface WebAVOutputDeviceMenuControllerHelper : NSObject {
-    MediaPlaybackTargetPickerMac* m_callback;
-}
-
-- (instancetype)initWithCallback:(MediaPlaybackTargetPickerMac*)callback;
-- (void)clearCallback;
-- (void)observeValueForKeyPath:(id)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
-@end
-
 namespace WebCore {
 
 MediaPlaybackTargetPickerMac::MediaPlaybackTargetPickerMac(MediaPlaybackTargetPicker::Client& client)
     : MediaPlaybackTargetPicker(client)
-    , m_outputDeviceMenuControllerDelegate(adoptNS([[WebAVOutputDeviceMenuControllerHelper alloc] initWithCallback:this]))
 {
 }
 
@@ -67,67 +59,36 @@
 MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac()
 {
     setClient(nullptr);
-    [m_outputDeviceMenuControllerDelegate clearCallback];
 }
 
 bool MediaPlaybackTargetPickerMac::externalOutputDeviceAvailable()
 {
-ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-    return devicePicker().externalOutputDeviceAvailable;
-ALLOW_DEPRECATED_DECLARATIONS_END
+    return routePicker().externalOutputDeviceAvailable();
 }
 
 Ref<MediaPlaybackTarget> MediaPlaybackTargetPickerMac::playbackTarget()
 {
-    AVOutputContext* context = m_outputDeviceMenuController ? [m_outputDeviceMenuController.get() outputContext] : nullptr;
-
-    return WebCore::MediaPlaybackTargetCocoa::create(context);
+    return WebCore::MediaPlaybackTargetCocoa::create(routePicker().outputContext());
 }
 
-AVOutputDeviceMenuController *MediaPlaybackTargetPickerMac::devicePicker()
+AVPlaybackTargetPicker& MediaPlaybackTargetPickerMac::routePicker()
 {
-    if (!getAVOutputDeviceMenuControllerClass())
-        return nullptr;
+    if (m_routePicker)
+        return *m_routePicker;
 
-    if (!m_outputDeviceMenuController) {
-        LOG(Media, "MediaPlaybackTargetPickerMac::devicePicker - allocating picker");
-
-        RetainPtr<AVOutputContext> context = adoptNS([PAL::allocAVOutputContextInstance() init]);
-        m_outputDeviceMenuController = adoptNS([allocAVOutputDeviceMenuControllerInstance() initWithOutputContext:context.get()]);
-
-        [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDeviceAvailableKeyName options:NSKeyValueObservingOptionNew context:nullptr];
-        [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDevicePickedKeyName options:NSKeyValueObservingOptionNew context:nullptr];
-
-        LOG(Media, "MediaPlaybackTargetPickerMac::devicePicker - allocated menu controller %p", m_outputDeviceMenuController.get());
-
-ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-        if (m_outputDeviceMenuController.get().externalOutputDeviceAvailable)
-            availableDevicesDidChange();
-ALLOW_DEPRECATED_DECLARATIONS_END
-    }
-
-    return m_outputDeviceMenuController.get();
+#if HAVE(AVROUTEPICKERVIEW)
+    if (AVRoutePickerViewTargetPicker::isAvailable())
+        m_routePicker = makeUnique<AVRoutePickerViewTargetPicker>(*this);
+    else
+#endif
+        m_routePicker = makeUnique<AVOutputDeviceMenuControllerTargetPicker>(*this);
+    
+    return *m_routePicker;
 }
 
-void MediaPlaybackTargetPickerMac::showPlaybackTargetPicker(const FloatRect& location, bool hasActiveRoute, bool useDarkAppearance)
+void MediaPlaybackTargetPickerMac::showPlaybackTargetPicker(PlatformView* view, const FloatRect& location, bool hasActiveRoute, bool useDarkAppearance)
 {
-    if (!client() || m_showingMenu)
-        return;
-
-    LOG(Media, "MediaPlaybackTargetPickerMac::showPlaybackTargetPicker - hasActiveRoute = %i", (int)hasActiveRoute);
-
-    m_showingMenu = true;
-
-ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-    bool targetSelected = [devicePicker() showMenuForRect:location appearanceName:(useDarkAppearance ? NSAppearanceNameVibrantDark : NSAppearanceNameVibrantLight) allowReselectionOfSelectedOutputDevice:!hasActiveRoute];
-ALLOW_DEPRECATED_DECLARATIONS_END
-
-    if (targetSelected != hasActiveRoute)
-        currentDeviceDidChange();
-    else if (!targetSelected && !hasActiveRoute)
-        playbackTargetPickerWasDismissed();
-
-    m_showingMenu = false;
+    routePicker().showPlaybackTargetPicker(view, location, hasActiveRoute, useDarkAppearance);
 }
 
 void MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets()
@@ -134,13 +95,13 @@
 {
     LOG(Media, "MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets");
 
-    devicePicker();
+    routePicker().startingMonitoringPlaybackTargets();
 }
 
 void MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets()
 {
     LOG(Media, "MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets");
-    // Nothing to do, AirPlay takes care of this automatically.
+    routePicker().stopMonitoringPlaybackTargets();
 }
 
 void MediaPlaybackTargetPickerMac::invalidatePlaybackTargets()
@@ -147,59 +108,27 @@
 {
     LOG(Media, "MediaPlaybackTargetPickerMac::invalidatePlaybackTargets");
 
-    if (m_outputDeviceMenuController) {
-        [m_outputDeviceMenuController removeObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDeviceAvailableKeyName];
-        [m_outputDeviceMenuController removeObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDevicePickedKeyName];
-        m_outputDeviceMenuController = nullptr;
-    }
+    m_routePicker = nullptr;
     currentDeviceDidChange();
 }
 
-} // namespace WebCore
-
-@implementation WebAVOutputDeviceMenuControllerHelper
-- (instancetype)initWithCallback:(MediaPlaybackTargetPickerMac*)callback
+void MediaPlaybackTargetPickerMac::pickerWasDismissed()
 {
-    if (!(self = [super init]))
-        return nil;
-
-    m_callback = callback;
-
-    return self;
+    playbackTargetPickerWasDismissed();
 }
 
-- (void)clearCallback
+void MediaPlaybackTargetPickerMac::availableDevicesChanged()
 {
-    m_callback = nil;
+    availableDevicesDidChange();
 }
 
-- (void)observeValueForKeyPath:(id)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+void MediaPlaybackTargetPickerMac::currentDeviceChanged()
 {
-    UNUSED_PARAM(object);
-    UNUSED_PARAM(change);
-    UNUSED_PARAM(context);
+    currentDeviceDidChange();
+}
 
-    if (!m_callback)
-        return;
 
-    LOG(Media, "MediaPlaybackTargetPickerMac::observeValueForKeyPath - key = %s", [keyPath UTF8String]);
+} // namespace WebCore
 
-    if (![keyPath isEqualToString:externalOutputDeviceAvailableKeyName] && ![keyPath isEqualToString:externalOutputDevicePickedKeyName])
-        return;
 
-    RetainPtr<WebAVOutputDeviceMenuControllerHelper> protectedSelf = self;
-    RetainPtr<NSString> protectedKeyPath = keyPath;
-    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedKeyPath = WTFMove(protectedKeyPath)] {
-        MediaPlaybackTargetPickerMac* callback = protectedSelf->m_callback;
-        if (!callback)
-            return;
-
-        if ([protectedKeyPath isEqualToString:externalOutputDeviceAvailableKeyName])
-            callback->availableDevicesDidChange();
-        else if ([protectedKeyPath isEqualToString:externalOutputDevicePickedKeyName])
-            callback->currentDeviceDidChange();
-    });
-}
-@end
-
 #endif // ENABLE(WIRELESS_PLAYBACK_TARGET)

Modified: trunk/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp (264662 => 264663)


--- trunk/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp	2020-07-21 17:46:28 UTC (rev 264663)
@@ -61,7 +61,7 @@
     return WebCore::MediaPlaybackTargetMock::create(m_deviceName, m_state);
 }
 
-void MediaPlaybackTargetPickerMock::showPlaybackTargetPicker(const FloatRect&, bool checkActiveRoute, bool useDarkAppearance)
+void MediaPlaybackTargetPickerMock::showPlaybackTargetPicker(PlatformView*, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance)
 {
     if (!client() || m_showingMenu)
         return;

Modified: trunk/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h (264662 => 264663)


--- trunk/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -43,7 +43,7 @@
 
     virtual ~MediaPlaybackTargetPickerMock();
 
-    void showPlaybackTargetPicker(const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) override;
+    void showPlaybackTargetPicker(PlatformView*, const FloatRect&, bool checkActiveRoute, bool useDarkAppearance) override;
     void startingMonitoringPlaybackTargets() override;
     void stopMonitoringPlaybackTargets() override;
     void invalidatePlaybackTargets() override;

Modified: trunk/Source/WebKit/ChangeLog (264662 => 264663)


--- trunk/Source/WebKit/ChangeLog	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKit/ChangeLog	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,3 +1,15 @@
+2020-07-21  Eric Carlson  <eric.carl...@apple.com>
+
+        Use AVRoutePickerView when available for choosing AirPlay devices
+        https://bugs.webkit.org/show_bug.cgi?id=213497
+        <rdar://problem/58610662>
+
+        Reviewed by Jer Noble.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/mac/WebPageProxyMac.mm:
+        (WebKit::WebPageProxy::platformView const): Add new override.
+
 2020-07-21  Jer Noble  <jer.no...@apple.com>
 
         [Cocoa] Adopt VTRegisterSupplementalVideoDecoderIfAvailable

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (264662 => 264663)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1534,6 +1534,7 @@
     void setShouldPlayToPlaybackTarget(WebCore::PlaybackTargetClientContextIdentifier, bool) final;
     void playbackTargetPickerWasDismissed(WebCore::PlaybackTargetClientContextIdentifier) final;
     bool alwaysOnLoggingAllowed() final { return isAlwaysOnLoggingAllowed(); }
+    PlatformView* platformView() const final;
 #endif
 
     void didChangeBackgroundColor();

Modified: trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm (264662 => 264663)


--- trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -673,6 +673,11 @@
     grantAccessToCurrentPasteboardData(NSPasteboardNameGeneral);
 }
 
+PlatformView* WebPageProxy::platformView() const
+{
+    return [pageClient().platformWindow() contentView];
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (264662 => 264663)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,3 +1,22 @@
+2020-07-21  Eric Carlson  <eric.carl...@apple.com>
+
+        Use AVRoutePickerView when available for choosing AirPlay devices
+        https://bugs.webkit.org/show_bug.cgi?id=213497
+        <rdar://problem/58610662>
+
+        Reviewed by Jer Noble.
+
+        * WebView/WebMediaPlaybackTargetPicker.h:
+        (WebMediaPlaybackTargetPicker::~WebMediaPlaybackTargetPicker): Deleted.
+        * WebView/WebMediaPlaybackTargetPicker.mm:
+        (WebMediaPlaybackTargetPicker::create):
+        (WebMediaPlaybackTargetPicker::WebMediaPlaybackTargetPicker):
+        (WebMediaPlaybackTargetPicker::invalidate):
+        (WebMediaPlaybackTargetPicker::platformView const): New override.
+
+        * WebView/WebView.mm:
+        (-[WebView _devicePicker]): Pass view to WebMediaPlaybackTargetPicker factory.
+
 2020-07-17  Sam Weinig  <wei...@apple.com>
 
         Remove final vestigates of SimpleColor

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebMediaPlaybackTargetPicker.h (264662 => 264663)


--- trunk/Source/WebKitLegacy/mac/WebView/WebMediaPlaybackTargetPicker.h	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebMediaPlaybackTargetPicker.h	2020-07-21 17:46:28 UTC (rev 264663)
@@ -32,6 +32,8 @@
 #include <WebCore/WebMediaSessionManagerClient.h>
 #include <wtf/Ref.h>
 
+OBJC_CLASS WebView;
+
 namespace WebCore {
 class FloatRect;
 class MediaPlaybackTarget;
@@ -41,10 +43,10 @@
 class WebMediaPlaybackTargetPicker : public WebCore::WebMediaSessionManagerClient {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static std::unique_ptr<WebMediaPlaybackTargetPicker> create(WebCore::Page&);
+    static std::unique_ptr<WebMediaPlaybackTargetPicker> create(WebView *, WebCore::Page&);
 
-    explicit WebMediaPlaybackTargetPicker(WebCore::Page&);
-    virtual ~WebMediaPlaybackTargetPicker() { }
+    explicit WebMediaPlaybackTargetPicker(WebView *, WebCore::Page&);
+    virtual ~WebMediaPlaybackTargetPicker() = default;
 
     void addPlaybackTargetPickerClient(WebCore::PlaybackTargetClientContextIdentifier);
     void removePlaybackTargetPickerClient(WebCore::PlaybackTargetClientContextIdentifier);
@@ -54,16 +56,18 @@
     void setMockMediaPlaybackTargetPickerState(const String&, WebCore::MediaPlaybackTargetContext::State);
     void mockMediaPlaybackTargetPickerDismissPopup();
 
-    // WebMediaSessionManagerClient
-    void setPlaybackTarget(WebCore::PlaybackTargetClientContextIdentifier, Ref<WebCore::MediaPlaybackTarget>&&) override;
-    void externalOutputDeviceAvailableDidChange(WebCore::PlaybackTargetClientContextIdentifier, bool) override;
-    void setShouldPlayToPlaybackTarget(WebCore::PlaybackTargetClientContextIdentifier, bool) override;
-    void playbackTargetPickerWasDismissed(WebCore::PlaybackTargetClientContextIdentifier) override;
-
     void invalidate();
 
 private:
+    // WebMediaSessionManagerClient
+    void setPlaybackTarget(WebCore::PlaybackTargetClientContextIdentifier, Ref<WebCore::MediaPlaybackTarget>&&) final;
+    void externalOutputDeviceAvailableDidChange(WebCore::PlaybackTargetClientContextIdentifier, bool) final;
+    void setShouldPlayToPlaybackTarget(WebCore::PlaybackTargetClientContextIdentifier, bool) final;
+    void playbackTargetPickerWasDismissed(WebCore::PlaybackTargetClientContextIdentifier) final;
+    PlatformView* platformView() const final;
+
     WebCore::Page* m_page;
+    WebView *m_webView;
 };
 
 #endif

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebMediaPlaybackTargetPicker.mm (264662 => 264663)


--- trunk/Source/WebKitLegacy/mac/WebView/WebMediaPlaybackTargetPicker.mm	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebMediaPlaybackTargetPicker.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -27,17 +27,19 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
 
+#import "WebView.h"
 #import <WebCore/MediaPlaybackTarget.h>
 #import <WebCore/Page.h>
 #import <WebCore/WebMediaSessionManager.h>
 
-std::unique_ptr<WebMediaPlaybackTargetPicker> WebMediaPlaybackTargetPicker::create(WebCore::Page& page)
+std::unique_ptr<WebMediaPlaybackTargetPicker> WebMediaPlaybackTargetPicker::create(WebView *webView, WebCore::Page& page)
 {
-    return makeUnique<WebMediaPlaybackTargetPicker>(page);
+    return makeUnique<WebMediaPlaybackTargetPicker>(webView, page);
 }
 
-WebMediaPlaybackTargetPicker::WebMediaPlaybackTargetPicker(WebCore::Page& page)
+WebMediaPlaybackTargetPicker::WebMediaPlaybackTargetPicker(WebView *webView, WebCore::Page& page)
     : m_page(&page)
+    , m_webView(webView)
 {
 }
 
@@ -109,7 +111,14 @@
 void WebMediaPlaybackTargetPicker::invalidate()
 {
     m_page = nullptr;
+    m_webView = nil;
     WebCore::WebMediaSessionManager::shared().removeAllPlaybackTargetPickerClients(*this);
 }
 
+PlatformView* WebMediaPlaybackTargetPicker::platformView() const
+{
+    ASSERT(m_webView);
+    return m_webView;
+}
+
 #endif

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebView.mm (264662 => 264663)


--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -9743,7 +9743,7 @@
 - (WebMediaPlaybackTargetPicker *) _devicePicker
 {
     if (!_private->m_playbackTargetPicker)
-        _private->m_playbackTargetPicker = WebMediaPlaybackTargetPicker::create(*_private->page);
+        _private->m_playbackTargetPicker = WebMediaPlaybackTargetPicker::create(self, *_private->page);
 
     return _private->m_playbackTargetPicker.get();
 }

Modified: trunk/Tools/ChangeLog (264662 => 264663)


--- trunk/Tools/ChangeLog	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Tools/ChangeLog	2020-07-21 17:46:28 UTC (rev 264663)
@@ -1,3 +1,16 @@
+2020-07-21  Eric Carlson  <eric.carl...@apple.com>
+
+        Use AVRoutePickerView when available for choosing AirPlay devices
+        https://bugs.webkit.org/show_bug.cgi?id=213497
+        <rdar://problem/58610662>
+
+        Reviewed by Jer Noble.
+
+        * TestWebKitAPI/Tests/WebCore/cocoa/AVFoundationSoftLinkTest.mm:
+        (TestWebKitAPI::TEST): Test AVOutputContextOutputDevicesDidChangeNotification.
+        Don't check AVRouteDetectorMultipleRoutesDetectedDidChangeNotification on watchOS,
+        we don't use it there.
+
 2020-07-21  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Fix ITP data summary when using the memory store and blocking all third-party cookies

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/AVFoundationSoftLinkTest.mm (264662 => 264663)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/AVFoundationSoftLinkTest.mm	2020-07-21 17:37:50 UTC (rev 264662)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/AVFoundationSoftLinkTest.mm	2020-07-21 17:46:28 UTC (rev 264663)
@@ -184,7 +184,6 @@
     EXPECT_TRUE([AVAudioSessionInterruptionNotification isEqualToString:@"AVAudioSessionInterruptionNotification"]);
     EXPECT_TRUE([AVAudioSessionInterruptionTypeKey isEqualToString:@"AVAudioSessionInterruptionTypeKey"]);
     EXPECT_TRUE([AVAudioSessionInterruptionOptionKey isEqualToString:@"AVAudioSessionInterruptionOptionKey"]);
-    EXPECT_TRUE([AVRouteDetectorMultipleRoutesDetectedDidChangeNotification isEqualToString:@"AVRouteDetectorMultipleRoutesDetectedDidChangeNotification"]);
 #if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
     EXPECT_TRUE([AVCaptureSessionErrorKey isEqualToString:@"AVCaptureSessionErrorKey"]);
     EXPECT_TRUE([AVCaptureSessionRuntimeErrorNotification isEqualToString:@"AVCaptureSessionRuntimeErrorNotification"]);
@@ -194,6 +193,12 @@
 #endif
 
 #endif
+    
+#if HAVE(AVROUTEPICKERVIEW)
+    EXPECT_TRUE([AVRouteDetectorMultipleRoutesDetectedDidChangeNotification isEqualToString:@"AVRouteDetectorMultipleRoutesDetectedDidChangeNotification"]);
+    EXPECT_TRUE([AVOutputContextOutputDevicesDidChangeNotification isEqualToString:@"AVOutputContextOutputDevicesDidChangeNotification"]);
+#endif // PLATFORM(WATCHOS)
+
 }
 
 #endif // PLATFORM(COCOA)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to