Diff
Modified: trunk/Source/WTF/ChangeLog (284821 => 284822)
--- trunk/Source/WTF/ChangeLog 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WTF/ChangeLog 2021-10-25 21:32:05 UTC (rev 284822)
@@ -1,3 +1,17 @@
+2021-10-25 Ayumi Kojima <[email protected]>
+
+ Unreviewed, reverting r284742.
+
+ Reverting because this commit may have casued a regression on
+ imported/w3c/web-platform-tests/speech-api/SpeechSynthesis-
+ speak-events.html
+
+ Reverted changeset:
+
+ "AX: Unify speech synthesizer platform usage for Mac/iOS"
+ https://bugs.webkit.org/show_bug.cgi?id=231895
+ https://commits.webkit.org/r284742
+
2021-10-24 Darin Adler <[email protected]>
[Cocoa] Adopt bridge_cast and makeVector in a few more places, including cases where adoptCF/NS was used incorrectly
Modified: trunk/Source/WTF/wtf/PlatformHave.h (284821 => 284822)
--- trunk/Source/WTF/wtf/PlatformHave.h 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WTF/wtf/PlatformHave.h 2021-10-25 21:32:05 UTC (rev 284822)
@@ -760,7 +760,7 @@
#endif
#endif
-#if ((PLATFORM(IOS) || PLATFORM(MACCATALYST)) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140300) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 120000)
+#if (PLATFORM(IOS) || PLATFORM(MACCATALYST)) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 140300
#if !defined(HAVE_AVSPEECHSYNTHESIS_SYSTEMVOICE)
#define HAVE_AVSPEECHSYNTHESIS_SYSTEMVOICE 1
#endif
@@ -772,6 +772,12 @@
#endif
#endif
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
+#if !defined(HAVE_SPEECHSYNTHESIS_MONTEREY_SPI)
+#define HAVE_SPEECHSYNTHESIS_MONTEREY_SPI 1
+#endif
+#endif
+
#if COMPILER(GCC_COMPATIBLE) && defined(__has_attribute)
#if __has_attribute(objc_direct) && (!PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000)
#if !defined(HAVE_NS_DIRECT_SUPPORT)
Modified: trunk/Source/WebCore/ChangeLog (284821 => 284822)
--- trunk/Source/WebCore/ChangeLog 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/ChangeLog 2021-10-25 21:32:05 UTC (rev 284822)
@@ -1,3 +1,17 @@
+2021-10-25 Ayumi Kojima <[email protected]>
+
+ Unreviewed, reverting r284742.
+
+ Reverting because this commit may have casued a regression on
+ imported/w3c/web-platform-tests/speech-api/SpeechSynthesis-
+ speak-events.html
+
+ Reverted changeset:
+
+ "AX: Unify speech synthesizer platform usage for Mac/iOS"
+ https://bugs.webkit.org/show_bug.cgi?id=231895
+ https://commits.webkit.org/r284742
+
2021-10-25 Chris Dumez <[email protected]>
Form navigations with target=_blank should not have an opener
Modified: trunk/Source/WebCore/PAL/ChangeLog (284821 => 284822)
--- trunk/Source/WebCore/PAL/ChangeLog 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/PAL/ChangeLog 2021-10-25 21:32:05 UTC (rev 284822)
@@ -1,3 +1,17 @@
+2021-10-25 Ayumi Kojima <[email protected]>
+
+ Unreviewed, reverting r284742.
+
+ Reverting because this commit may have casued a regression on
+ imported/w3c/web-platform-tests/speech-api/SpeechSynthesis-
+ speak-events.html
+
+ Reverted changeset:
+
+ "AX: Unify speech synthesizer platform usage for Mac/iOS"
+ https://bugs.webkit.org/show_bug.cgi?id=231895
+ https://commits.webkit.org/r284742
+
2021-10-23 Chris Fleizach <[email protected]>
AX: Unify speech synthesizer platform usage for Mac/iOS
Modified: trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj (284821 => 284822)
--- trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj 2021-10-25 21:32:05 UTC (rev 284822)
@@ -169,6 +169,7 @@
A10826F91F576292004772AC /* WebPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = A10826F71F576292004772AC /* WebPanel.h */; };
A10826FA1F576292004772AC /* WebPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A10826F81F576292004772AC /* WebPanel.mm */; };
A10826FE1F58A433004772AC /* NSGraphicsSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A10826FD1F58A433004772AC /* NSGraphicsSPI.h */; };
+ A1175B491F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A1175B481F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h */; };
A1175B4B1F6B2D7E00C4B9F0 /* NSCellSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A1175B4A1F6B2D7E00C4B9F0 /* NSCellSPI.h */; };
A1175B4E1F6B337300C4B9F0 /* PopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = A1175B4C1F6B337300C4B9F0 /* PopupMenu.h */; };
A1175B4F1F6B337300C4B9F0 /* PopupMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1175B4D1F6B337300C4B9F0 /* PopupMenu.mm */; };
@@ -395,6 +396,7 @@
A10826F71F576292004772AC /* WebPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebPanel.h; sourceTree = "<group>"; };
A10826F81F576292004772AC /* WebPanel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPanel.mm; sourceTree = "<group>"; };
A10826FD1F58A433004772AC /* NSGraphicsSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSGraphicsSPI.h; sourceTree = "<group>"; };
+ A1175B481F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpeechSynthesisSPI.h; sourceTree = "<group>"; };
A1175B4A1F6B2D7E00C4B9F0 /* NSCellSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSCellSPI.h; sourceTree = "<group>"; };
A1175B4C1F6B337300C4B9F0 /* PopupMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PopupMenu.h; sourceTree = "<group>"; };
A1175B4D1F6B337300C4B9F0 /* PopupMenu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PopupMenu.mm; sourceTree = "<group>"; };
@@ -641,6 +643,7 @@
0C7785841F45130F00F4EBB6 /* NSWindowSPI.h */,
0C7785851F45130F00F4EBB6 /* PIPSPI.h */,
0C7785871F45130F00F4EBB6 /* QuickLookMacSPI.h */,
+ A1175B481F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h */,
71B1141F26823ACD004D6701 /* SystemPreviewSPI.h */,
0C7785881F45130F00F4EBB6 /* TelephonyUtilitiesSPI.h */,
);
@@ -1009,6 +1012,7 @@
A3788E981F05B6CE00679425 /* Sound.h in Headers */,
93B38EBE25821CB600198E63 /* SpeechSoftLink.h in Headers */,
93B38EC225821D2200198E63 /* SpeechSPI.h in Headers */,
+ A1175B491F6AFF8E00C4B9F0 /* SpeechSynthesisSPI.h in Headers */,
0C5AF9211F43A4C7002EAC02 /* SQLite3SPI.h in Headers */,
71B1142026823ACD004D6701 /* SystemPreviewSPI.h in Headers */,
31308B1420A21705003FB929 /* SystemPreviewSPI.h in Headers */,
Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h (284821 => 284822)
--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h 2021-10-25 21:32:05 UTC (rev 284822)
@@ -76,9 +76,6 @@
#if PLATFORM(IOS_FAMILY)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVAudioSession)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPersistableContentKeyRequest)
-#endif
-
-#if PLATFORM(COCOA)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVSpeechSynthesisVoice)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVSpeechSynthesizer)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVSpeechUtterance)
Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm (284821 => 284822)
--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm 2021-10-25 21:32:05 UTC (rev 284822)
@@ -102,9 +102,6 @@
#if PLATFORM(IOS_FAMILY)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVAudioSession, PAL_EXPORT)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPersistableContentKeyRequest, PAL_EXPORT)
-#endif
-
-#if PLATFORM(COCOA)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVSpeechSynthesisVoice, PAL_EXPORT)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVSpeechSynthesizer, PAL_EXPORT)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVSpeechUtterance, PAL_EXPORT)
Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/AXSpeechManagerSPI.h (284821 => 284822)
--- trunk/Source/WebCore/PAL/pal/spi/cocoa/AXSpeechManagerSPI.h 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/AXSpeechManagerSPI.h 2021-10-25 21:32:05 UTC (rev 284822)
@@ -25,7 +25,7 @@
#pragma once
-#if PLATFORM(COCOA)
+#if PLATFORM(IOS_FAMILY)
// FIXME: Undo when isSystemVoice is available in all SDKs.
#if USE(APPLE_INTERNAL_SDK) && 0
@@ -42,5 +42,5 @@
#endif // USE(APPLE_INTERNAL_SDK)
-#endif // PLATFORM(COCOA)
+#endif // PLATFORM(IOS_FAMILY)
Added: trunk/Source/WebCore/PAL/pal/spi/mac/SpeechSynthesisSPI.h (0 => 284822)
--- trunk/Source/WebCore/PAL/pal/spi/mac/SpeechSynthesisSPI.h (rev 0)
+++ trunk/Source/WebCore/PAL/pal/spi/mac/SpeechSynthesisSPI.h 2021-10-25 21:32:05 UTC (rev 284822)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017-2021 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 USE(APPLE_INTERNAL_SDK)
+
+#include <ApplicationServices/ApplicationServicesPriv.h>
+
+#endif
+
+WTF_EXTERN_C_BEGIN
+
+CFArrayRef CopySpeechSynthesisVoicesForMode(CFTypeRef mode);
+#if HAVE(SPEECHSYNTHESIS_MONTEREY_SPI)
+CFStringRef CopyIdentifierStringForPreferredVoiceInListWithLocale(CFArrayRef voices, CFLocaleRef);
+#else
+CFStringRef GetIdentifierStringForPreferredVoiceInListWithLocale(CFArrayRef voices, CFLocaleRef);
+#endif
+
+WTF_EXTERN_C_END
Modified: trunk/Source/WebCore/SourcesCocoa.txt (284821 => 284822)
--- trunk/Source/WebCore/SourcesCocoa.txt 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/SourcesCocoa.txt 2021-10-25 21:32:05 UTC (rev 284822)
@@ -256,7 +256,6 @@
platform/cocoa/PasteboardCocoa.mm
platform/cocoa/PasteboardCustomDataCocoa.mm
platform/cocoa/PlatformPasteboardCocoa.mm
-platform/cocoa/PlatformSpeechSynthesizerCocoa.mm @no-unify
platform/cocoa/PlaybackSessionModelMediaElement.mm
platform/cocoa/PowerSourceNotifier.mm
platform/cocoa/RemoteCommandListenerCocoa.mm
@@ -440,6 +439,7 @@
platform/ios/PlatformEventFactoryIOS.mm @no-unify
platform/ios/PlatformPasteboardIOS.mm
platform/ios/PlatformScreenIOS.mm
+platform/ios/PlatformSpeechSynthesizerIOS.mm @no-unify
platform/ios/PlaybackSessionInterfaceAVKit.mm @no-unify
platform/ios/PreviewConverterIOS.mm
platform/ios/QuickLook.mm
@@ -486,6 +486,7 @@
platform/mac/PlatformEventFactoryMac.mm
platform/mac/PlatformPasteboardMac.mm
platform/mac/PlatformScreenMac.mm
+platform/mac/PlatformSpeechSynthesizerMac.mm
platform/mac/PlaybackSessionInterfaceMac.mm @no-unify
platform/mac/PluginBlocklist.mm
platform/mac/PowerObserverMac.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (284821 => 284822)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-10-25 21:32:05 UTC (rev 284822)
@@ -3710,7 +3710,7 @@
A9D248010D757E6900FDF959 /* JSDOMPluginArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D247FD0D757E6900FDF959 /* JSDOMPluginArray.h */; };
A9D248070D757E7D00FDF959 /* JSDOMMimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D248030D757E7D00FDF959 /* JSDOMMimeType.h */; };
A9D248090D757E7D00FDF959 /* JSDOMMimeTypeArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D248050D757E7D00FDF959 /* JSDOMMimeTypeArray.h */; };
- AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerCocoa.mm */; };
+ AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerIOS.mm */; };
AA21ECCD0ABF0FC6002B834C /* CSSCursorImageValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0978EE0ABAA6E100874480 /* CSSCursorImageValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
AA2A5ACE16A485FD00975A25 /* SpeechSynthesisVoice.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2A5AC716A485D500975A25 /* SpeechSynthesisVoice.h */; };
AA2A5AD016A4860400975A25 /* SpeechSynthesisUtterance.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2A5AC516A485D500975A25 /* SpeechSynthesisUtterance.h */; };
@@ -7301,6 +7301,7 @@
29D7BCF91444AF7D0070619C /* AccessibilitySpinButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySpinButton.h; sourceTree = "<group>"; };
29E04A27BED2F81F98E9022B /* JSBeforeUnloadEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBeforeUnloadEvent.h; sourceTree = "<group>"; };
29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformSpeechSynthesizer.h; sourceTree = "<group>"; };
+ 29E4D8E016B0959800C84704 /* PlatformSpeechSynthesizerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerMac.mm; sourceTree = "<group>"; };
29FAF4B5195AB08900A522DC /* TextUndoInsertionMarkupMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextUndoInsertionMarkupMac.h; sourceTree = "<group>"; };
2A4107A026CB66ED003BF797 /* CSSKeywordValue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CSSKeywordValue.cpp; sourceTree = "<group>"; };
2A4107A226CB66ED003BF797 /* CSSKeywordValue.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = CSSKeywordValue.idl; sourceTree = "<group>"; };
@@ -13629,7 +13630,7 @@
AADEFE4325AF4FCB0040DD67 /* FocusOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FocusOptions.h; sourceTree = "<group>"; };
AAE27B7416CBFC0D00623043 /* PlatformSpeechSynthesizerMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformSpeechSynthesizerMock.cpp; sourceTree = "<group>"; };
AAE27B7516CBFC0D00623043 /* PlatformSpeechSynthesizerMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformSpeechSynthesizerMock.h; sourceTree = "<group>"; };
- AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerCocoa.mm; sourceTree = "<group>"; };
+ AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerIOS.mm; sourceTree = "<group>"; };
AAF5B7B11524B4BD0004CB49 /* WebSocketFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketFrame.cpp; sourceTree = "<group>"; };
AB23A32509BBA7D00067CC53 /* BeforeTextInsertedEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BeforeTextInsertedEvent.cpp; sourceTree = "<group>"; };
AB23A32609BBA7D00067CC53 /* BeforeTextInsertedEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BeforeTextInsertedEvent.h; sourceTree = "<group>"; };
@@ -22390,6 +22391,7 @@
BCAA486D14A052530088FAC4 /* PlatformEventFactoryMac.mm */,
C5F765BA14E1ECF4006C899B /* PlatformPasteboardMac.mm */,
BC94D1070C274F88006BC617 /* PlatformScreenMac.mm */,
+ 29E4D8E016B0959800C84704 /* PlatformSpeechSynthesizerMac.mm */,
CDA29A151CBDA56C00901CCF /* PlaybackSessionInterfaceMac.h */,
CDA29A141CBDA56C00901CCF /* PlaybackSessionInterfaceMac.mm */,
1AFFC44F1D5E7EC700267A66 /* PluginBlocklist.h */,
@@ -25060,6 +25062,7 @@
26601EBE14B3B9AD0012C0FE /* PlatformEventFactoryIOS.mm */,
C5278B0B17F212EA003A2998 /* PlatformPasteboardIOS.mm */,
E45390320EAFD637003695C8 /* PlatformScreenIOS.mm */,
+ AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerIOS.mm */,
CDA29A2E1CBF73FC00901CCF /* PlaybackSessionInterfaceAVKit.h */,
CDA29A2F1CBF73FC00901CCF /* PlaybackSessionInterfaceAVKit.mm */,
A1C150771E3F2B3E0032C98C /* PreviewConverterIOS.mm */,
@@ -25218,7 +25221,6 @@
9BED2CAF1F7CC06200666018 /* PasteboardCocoa.mm */,
F4FB35002350C96200F0094A /* PasteboardCustomDataCocoa.mm */,
F4628A9E234D3BBF00BC884C /* PlatformPasteboardCocoa.mm */,
- AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerCocoa.mm */,
52B0D4BD1C57FD1E0077CE53 /* PlatformView.h */,
CDA29A0A1CBD9A7400901CCF /* PlaybackSessionModel.h */,
CDA29A0D1CBD9CFE00901CCF /* PlaybackSessionModelMediaElement.h */,
@@ -36891,7 +36893,7 @@
1A569D1A0D7E2B82007C3983 /* objc_utility.mm in Sources */,
E16982601134636A00894115 /* ObjCRuntimeObject.mm in Sources */,
CEA284662141E84900E407E8 /* PlatformEventFactoryIOS.mm in Sources */,
- AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerCocoa.mm in Sources */,
+ AA12DF491743DF83004DAFDF /* PlatformSpeechSynthesizerIOS.mm in Sources */,
CDA29A301CBF74D400901CCF /* PlaybackSessionInterfaceAVKit.mm in Sources */,
CDA29A161CBDA56C00901CCF /* PlaybackSessionInterfaceMac.mm in Sources */,
419242492127B93E00634FCF /* RealtimeOutgoingVideoSourceCocoa.mm in Sources */,
Deleted: trunk/Source/WebCore/platform/cocoa/PlatformSpeechSynthesizerCocoa.mm (284821 => 284822)
--- trunk/Source/WebCore/platform/cocoa/PlatformSpeechSynthesizerCocoa.mm 2021-10-25 21:27:18 UTC (rev 284821)
+++ trunk/Source/WebCore/platform/cocoa/PlatformSpeechSynthesizerCocoa.mm 2021-10-25 21:32:05 UTC (rev 284822)
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2013 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 "PlatformSpeechSynthesizer.h"
-
-#if ENABLE(SPEECH_SYNTHESIS) && PLATFORM(COCOA)
-
-#import "PlatformSpeechSynthesisUtterance.h"
-#import "PlatformSpeechSynthesisVoice.h"
-
-#if __has_include(<AVFAudio/AVSpeechSynthesis.h>)
-#import <AVFAudio/AVSpeechSynthesis.h>
-#else
-#import <AVFoundation/AVFoundation.h>
-#endif
-
-#import <pal/spi/cocoa/AXSpeechManagerSPI.h>
-#import <wtf/BlockObjCExceptions.h>
-#import <wtf/RetainPtr.h>
-
-#import <pal/cocoa/AVFoundationSoftLink.h>
-
-static float getAVSpeechUtteranceDefaultSpeechRate()
-{
- static float value;
- static void* symbol;
- if (!symbol) {
- void* symbol = dlsym(PAL::AVFoundationLibrary(), "AVSpeechUtteranceDefaultSpeechRate");
- RELEASE_ASSERT_WITH_MESSAGE(symbol, "%s", dlerror());
- value = *static_cast<float const *>(symbol);
- }
- return value;
-}
-
-static float getAVSpeechUtteranceMaximumSpeechRate()
-{
- static float value;
- static void* symbol;
- if (!symbol) {
- void* symbol = dlsym(PAL::AVFoundationLibrary(), "AVSpeechUtteranceMaximumSpeechRate");
- RELEASE_ASSERT_WITH_MESSAGE(symbol, "%s", dlerror());
- value = *static_cast<float const *>(symbol);
- }
- return value;
-}
-
-#define AVSpeechUtteranceDefaultSpeechRate getAVSpeechUtteranceDefaultSpeechRate()
-#define AVSpeechUtteranceMaximumSpeechRate getAVSpeechUtteranceMaximumSpeechRate()
-
-@interface WebSpeechSynthesisWrapper : NSObject<AVSpeechSynthesizerDelegate> {
- WebCore::PlatformSpeechSynthesizer* m_synthesizerObject;
- // Hold a Ref to the utterance so that it won't disappear until the synth is done with it.
- RefPtr<WebCore::PlatformSpeechSynthesisUtterance> m_utterance;
-
- RetainPtr<AVSpeechSynthesizer> m_synthesizer;
-}
-
-- (WebSpeechSynthesisWrapper *)initWithSpeechSynthesizer:(WebCore::PlatformSpeechSynthesizer*)synthesizer;
-- (void)speakUtterance:(RefPtr<WebCore::PlatformSpeechSynthesisUtterance>&&)utterance;
-
-@end
-
-@implementation WebSpeechSynthesisWrapper
-
-- (WebSpeechSynthesisWrapper *)initWithSpeechSynthesizer:(WebCore::PlatformSpeechSynthesizer*)synthesizer
-{
- if (!(self = [super init]))
- return nil;
-
- m_synthesizerObject = synthesizer;
- return self;
-}
-
-- (float)mapSpeechRateToPlatformRate:(float)rate
-{
- // WebSpeech says to go from .1 -> 10 (default 1)
- // AVSpeechSynthesizer asks for 0 -> 1 (default. 5)
- if (rate < 1)
- rate *= AVSpeechUtteranceDefaultSpeechRate;
- else
- rate = AVSpeechUtteranceDefaultSpeechRate + ((rate - 1) * (AVSpeechUtteranceMaximumSpeechRate - AVSpeechUtteranceDefaultSpeechRate));
-
- return rate;
-}
-
-- (void)speakUtterance:(RefPtr<WebCore::PlatformSpeechSynthesisUtterance>&&)utterance
-{
- // When speak is called we should not have an existing speech utterance outstanding.
- ASSERT(!m_utterance);
- ASSERT(utterance);
-
- if (!utterance)
- return;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- if (!m_synthesizer) {
- m_synthesizer = adoptNS([PAL::allocAVSpeechSynthesizerInstance() init]);
- [m_synthesizer setDelegate:self];
- }
-
- // Choose the best voice, by first looking at the utterance voice, then the utterance language,
- // then choose the default language.
- WebCore::PlatformSpeechSynthesisVoice* utteranceVoice = utterance->voice();
- NSString *voiceLanguage = nil;
- if (!utteranceVoice) {
- if (utterance->lang().isEmpty())
- voiceLanguage = [PAL::getAVSpeechSynthesisVoiceClass() currentLanguageCode];
- else
- voiceLanguage = utterance->lang();
- } else
- voiceLanguage = utterance->voice()->lang();
-
- AVSpeechSynthesisVoice *avVoice = nil;
- if (voiceLanguage)
- avVoice = [PAL::getAVSpeechSynthesisVoiceClass() voiceWithLanguage:voiceLanguage];
-
- AVSpeechUtterance *avUtterance = [PAL::getAVSpeechUtteranceClass() speechUtteranceWithString:utterance->text()];
-
- [avUtterance setRate:[self mapSpeechRateToPlatformRate:utterance->rate()]];
- [avUtterance setVolume:utterance->volume()];
- [avUtterance setPitchMultiplier:utterance->pitch()];
- [avUtterance setVoice:avVoice];
- m_utterance = WTFMove(utterance);
-
- [m_synthesizer speakUtterance:avUtterance];
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-- (void)pause
-{
- if (!m_utterance)
- return;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- [m_synthesizer pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-- (void)resume
-{
- if (!m_utterance)
- return;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- [m_synthesizer continueSpeaking];
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-- (void)cancel
-{
- if (!m_utterance)
- return;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- [m_synthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance
-{
- UNUSED_PARAM(synthesizer);
- UNUSED_PARAM(utterance);
- if (!m_utterance)
- return;
-
- m_synthesizerObject->client()->didStartSpeaking(*m_utterance);
-}
-
-- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
-{
- UNUSED_PARAM(synthesizer);
- UNUSED_PARAM(utterance);
- if (!m_utterance)
- return;
-
- // Clear the m_utterance variable in case finish speaking kicks off a new speaking job immediately.
- RefPtr<WebCore::PlatformSpeechSynthesisUtterance> protectedUtterance = m_utterance;
- m_utterance = nullptr;
-
- m_synthesizerObject->client()->didFinishSpeaking(*protectedUtterance);
-}
-
-- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance
-{
- UNUSED_PARAM(synthesizer);
- UNUSED_PARAM(utterance);
- if (!m_utterance)
- return;
-
- m_synthesizerObject->client()->didPauseSpeaking(*m_utterance);
-}
-
-- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance
-{
- UNUSED_PARAM(synthesizer);
- UNUSED_PARAM(utterance);
- if (!m_utterance)
- return;
-
- m_synthesizerObject->client()->didResumeSpeaking(*m_utterance);
-}
-
-- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance
-{
- UNUSED_PARAM(synthesizer);
- UNUSED_PARAM(utterance);
- if (!m_utterance)
- return;
-
- // Clear the m_utterance variable in case finish speaking kicks off a new speaking job immediately.
- RefPtr<WebCore::PlatformSpeechSynthesisUtterance> protectedUtterance = m_utterance;
- m_utterance = nullptr;
-
- m_synthesizerObject->client()->didFinishSpeaking(*protectedUtterance);
-}
-
-- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance
-{
- UNUSED_PARAM(synthesizer);
- UNUSED_PARAM(utterance);
-
- if (!m_utterance)
- return;
-
- // AVSpeechSynthesizer only supports word boundaries.
- m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechBoundary::SpeechWordBoundary, characterRange.location);
-}
-
-@end
-
-namespace WebCore {
-
-PlatformSpeechSynthesizer::PlatformSpeechSynthesizer(PlatformSpeechSynthesizerClient* client)
- : m_speechSynthesizerClient(client)
-{
-}
-
-PlatformSpeechSynthesizer::~PlatformSpeechSynthesizer()
-{
-}
-
-void PlatformSpeechSynthesizer::initializeVoiceList()
-{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- for (AVSpeechSynthesisVoice *voice in [PAL::getAVSpeechSynthesisVoiceClass() speechVoices]) {
- NSString *language = [voice language];
- bool isDefault = true;
- NSString *voiceURI = [voice identifier];
- NSString *name = [voice name];
-
- // Only show built-in voices when requesting through WebKit to reduce fingerprinting surface area.
-#if HAVE(AVSPEECHSYNTHESIS_SYSTEMVOICE)
- // FIXME: Remove respondsToSelector check when is available on all SDKs.
- BOOL includeVoice = NO;
- if ([voice respondsToSelector:@selector(isSystemVoice)])
- includeVoice = voice.isSystemVoice;
- else
- includeVoice = voice.quality == AVSpeechSynthesisVoiceQualityDefault;
- if (includeVoice)
-#else
- // AVSpeechSynthesis on macOS does not support quality property correctly.
- if (voice.quality == AVSpeechSynthesisVoiceQualityDefault
- || (TARGET_OS_OSX && ![voiceURI hasSuffix:@"premium"]))
-#endif
- m_voiceList.append(PlatformSpeechSynthesisVoice::create(voiceURI, name, language, true, isDefault));
- }
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-void PlatformSpeechSynthesizer::pause()
-{
- [m_platformSpeechWrapper pause];
-}
-
-void PlatformSpeechSynthesizer::resume()
-{
- [m_platformSpeechWrapper resume];
-}
-
-void PlatformSpeechSynthesizer::speak(RefPtr<PlatformSpeechSynthesisUtterance>&& utterance)
-{
- if (!m_platformSpeechWrapper)
- m_platformSpeechWrapper = adoptNS([[WebSpeechSynthesisWrapper alloc] initWithSpeechSynthesizer:this]);
-
- [m_platformSpeechWrapper speakUtterance:utterance.get()];
-}
-
-void PlatformSpeechSynthesizer::cancel()
-{
- [m_platformSpeechWrapper cancel];
-}
-
-void PlatformSpeechSynthesizer::resetState()
-{
- [m_platformSpeechWrapper cancel];
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SPEECH_SYNTHESIS) && PLATFORM(COCOA)
Copied: trunk/Source/WebCore/platform/ios/PlatformSpeechSynthesizerIOS.mm (from rev 284821, trunk/Source/WebCore/platform/cocoa/PlatformSpeechSynthesizerCocoa.mm) (0 => 284822)
--- trunk/Source/WebCore/platform/ios/PlatformSpeechSynthesizerIOS.mm (rev 0)
+++ trunk/Source/WebCore/platform/ios/PlatformSpeechSynthesizerIOS.mm 2021-10-25 21:32:05 UTC (rev 284822)
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2013 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 "PlatformSpeechSynthesizer.h"
+
+#if ENABLE(SPEECH_SYNTHESIS) && PLATFORM(IOS_FAMILY)
+
+#import "PlatformSpeechSynthesisUtterance.h"
+#import "PlatformSpeechSynthesisVoice.h"
+#import <AVFoundation/AVSpeechSynthesis.h>
+#import <pal/spi/cocoa/AXSpeechManagerSPI.h>
+#import <wtf/BlockObjCExceptions.h>
+#import <wtf/RetainPtr.h>
+
+#import <pal/cocoa/AVFoundationSoftLink.h>
+
+static float getAVSpeechUtteranceDefaultSpeechRate()
+{
+ static float value;
+ static void* symbol;
+ if (!symbol) {
+ void* symbol = dlsym(PAL::AVFoundationLibrary(), "AVSpeechUtteranceDefaultSpeechRate");
+ RELEASE_ASSERT_WITH_MESSAGE(symbol, "%s", dlerror());
+ value = *static_cast<float const *>(symbol);
+ }
+ return value;
+}
+
+static float getAVSpeechUtteranceMaximumSpeechRate()
+{
+ static float value;
+ static void* symbol;
+ if (!symbol) {
+ void* symbol = dlsym(PAL::AVFoundationLibrary(), "AVSpeechUtteranceMaximumSpeechRate");
+ RELEASE_ASSERT_WITH_MESSAGE(symbol, "%s", dlerror());
+ value = *static_cast<float const *>(symbol);
+ }
+ return value;
+}
+
+#define AVSpeechUtteranceDefaultSpeechRate getAVSpeechUtteranceDefaultSpeechRate()
+#define AVSpeechUtteranceMaximumSpeechRate getAVSpeechUtteranceMaximumSpeechRate()
+
+@interface WebSpeechSynthesisWrapper : NSObject<AVSpeechSynthesizerDelegate>
+{
+ WebCore::PlatformSpeechSynthesizer* m_synthesizerObject;
+ // Hold a Ref to the utterance so that it won't disappear until the synth is done with it.
+ RefPtr<WebCore::PlatformSpeechSynthesisUtterance> m_utterance;
+
+ RetainPtr<AVSpeechSynthesizer> m_synthesizer;
+}
+
+- (WebSpeechSynthesisWrapper *)initWithSpeechSynthesizer:(WebCore::PlatformSpeechSynthesizer*)synthesizer;
+- (void)speakUtterance:(RefPtr<WebCore::PlatformSpeechSynthesisUtterance>&&)utterance;
+
+@end
+
+@implementation WebSpeechSynthesisWrapper
+
+- (WebSpeechSynthesisWrapper *)initWithSpeechSynthesizer:(WebCore::PlatformSpeechSynthesizer*)synthesizer
+{
+ if (!(self = [super init]))
+ return nil;
+
+ m_synthesizerObject = synthesizer;
+ return self;
+}
+
+- (float)mapSpeechRateToPlatformRate:(float)rate
+{
+ // WebSpeech says to go from .1 -> 10 (default 1)
+ // AVSpeechSynthesizer asks for 0 -> 1 (default. 5)
+ if (rate < 1)
+ rate *= AVSpeechUtteranceDefaultSpeechRate;
+ else
+ rate = AVSpeechUtteranceDefaultSpeechRate + ((rate - 1) * (AVSpeechUtteranceMaximumSpeechRate - AVSpeechUtteranceDefaultSpeechRate));
+
+ return rate;
+}
+
+- (void)speakUtterance:(RefPtr<WebCore::PlatformSpeechSynthesisUtterance>&&)utterance
+{
+ // When speak is called we should not have an existing speech utterance outstanding.
+ ASSERT(!m_utterance);
+ ASSERT(utterance);
+
+ if (!utterance)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ if (!m_synthesizer) {
+ m_synthesizer = adoptNS([PAL::allocAVSpeechSynthesizerInstance() init]);
+ [m_synthesizer setDelegate:self];
+ }
+
+ // Choose the best voice, by first looking at the utterance voice, then the utterance language,
+ // then choose the default language.
+ WebCore::PlatformSpeechSynthesisVoice* utteranceVoice = utterance->voice();
+ NSString *voiceLanguage = nil;
+ if (!utteranceVoice) {
+ if (utterance->lang().isEmpty())
+ voiceLanguage = [PAL::getAVSpeechSynthesisVoiceClass() currentLanguageCode];
+ else
+ voiceLanguage = utterance->lang();
+ } else
+ voiceLanguage = utterance->voice()->lang();
+
+ AVSpeechSynthesisVoice *avVoice = nil;
+ if (voiceLanguage)
+ avVoice = [PAL::getAVSpeechSynthesisVoiceClass() voiceWithLanguage:voiceLanguage];
+
+ AVSpeechUtterance *avUtterance = [PAL::getAVSpeechUtteranceClass() speechUtteranceWithString:utterance->text()];
+
+ [avUtterance setRate:[self mapSpeechRateToPlatformRate:utterance->rate()]];
+ [avUtterance setVolume:utterance->volume()];
+ [avUtterance setPitchMultiplier:utterance->pitch()];
+ [avUtterance setVoice:avVoice];
+ m_utterance = WTFMove(utterance);
+
+ [m_synthesizer speakUtterance:avUtterance];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+- (void)pause
+{
+ if (!m_utterance)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_synthesizer pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+- (void)resume
+{
+ if (!m_utterance)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_synthesizer continueSpeaking];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+- (void)cancel
+{
+ if (!m_utterance)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_synthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance
+{
+ UNUSED_PARAM(synthesizer);
+ UNUSED_PARAM(utterance);
+ if (!m_utterance)
+ return;
+
+ m_synthesizerObject->client()->didStartSpeaking(*m_utterance);
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
+{
+ UNUSED_PARAM(synthesizer);
+ UNUSED_PARAM(utterance);
+ if (!m_utterance)
+ return;
+
+ // Clear the m_utterance variable in case finish speaking kicks off a new speaking job immediately.
+ RefPtr<WebCore::PlatformSpeechSynthesisUtterance> platformUtterance = m_utterance;
+ m_utterance = nullptr;
+
+ m_synthesizerObject->client()->didFinishSpeaking(*platformUtterance);
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance
+{
+ UNUSED_PARAM(synthesizer);
+ UNUSED_PARAM(utterance);
+ if (!m_utterance)
+ return;
+
+ m_synthesizerObject->client()->didPauseSpeaking(*m_utterance);
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance
+{
+ UNUSED_PARAM(synthesizer);
+ UNUSED_PARAM(utterance);
+ if (!m_utterance)
+ return;
+
+ m_synthesizerObject->client()->didResumeSpeaking(*m_utterance);
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance
+{
+ UNUSED_PARAM(synthesizer);
+ UNUSED_PARAM(utterance);
+ if (!m_utterance)
+ return;
+
+ // Clear the m_utterance variable in case finish speaking kicks off a new speaking job immediately.
+ RefPtr<WebCore::PlatformSpeechSynthesisUtterance> platformUtterance = m_utterance;
+ m_utterance = nullptr;
+
+ m_synthesizerObject->client()->didFinishSpeaking(*platformUtterance);
+}
+
+- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance
+{
+ UNUSED_PARAM(synthesizer);
+ UNUSED_PARAM(utterance);
+
+ if (!m_utterance)
+ return;
+
+ // iOS only supports word boundaries.
+ m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechBoundary::SpeechWordBoundary, characterRange.location);
+}
+
+@end
+
+namespace WebCore {
+
+PlatformSpeechSynthesizer::PlatformSpeechSynthesizer(PlatformSpeechSynthesizerClient* client)
+ : m_speechSynthesizerClient(client)
+{
+}
+
+PlatformSpeechSynthesizer::~PlatformSpeechSynthesizer()
+{
+}
+
+void PlatformSpeechSynthesizer::initializeVoiceList()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ for (AVSpeechSynthesisVoice *voice in [PAL::getAVSpeechSynthesisVoiceClass() speechVoices]) {
+ NSString *language = [voice language];
+ bool isDefault = true;
+ NSString *voiceURI = [voice identifier];
+ NSString *name = [voice name];
+
+ // Only show built-in voices when requesting through WebKit to reduce fingerprinting surface area.
+#if HAVE(AVSPEECHSYNTHESIS_SYSTEMVOICE)
+ // FIXME: Remove respondsToSelector check when is available on all SDKs.
+ BOOL includeVoice = NO;
+ if ([voice respondsToSelector:@selector(isSystemVoice)])
+ includeVoice = voice.isSystemVoice;
+ else
+ includeVoice = voice.quality == AVSpeechSynthesisVoiceQualityDefault;
+ if (includeVoice)
+#else
+ if (voice.quality == AVSpeechSynthesisVoiceQualityDefault)
+#endif
+ m_voiceList.append(PlatformSpeechSynthesisVoice::create(voiceURI, name, language, true, isDefault));
+ }
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformSpeechSynthesizer::pause()
+{
+ [m_platformSpeechWrapper pause];
+}
+
+void PlatformSpeechSynthesizer::resume()
+{
+ [m_platformSpeechWrapper resume];
+}
+
+void PlatformSpeechSynthesizer::speak(RefPtr<PlatformSpeechSynthesisUtterance>&& utterance)
+{
+ if (!m_platformSpeechWrapper)
+ m_platformSpeechWrapper = adoptNS([[WebSpeechSynthesisWrapper alloc] initWithSpeechSynthesizer:this]);
+
+ [m_platformSpeechWrapper speakUtterance:utterance.get()];
+}
+
+void PlatformSpeechSynthesizer::cancel()
+{
+ [m_platformSpeechWrapper cancel];
+}
+
+void PlatformSpeechSynthesizer::resetState()
+{
+ [m_platformSpeechWrapper cancel];
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SPEECH_SYNTHESIS) && PLATFORM(IOS_FAMILY)
Added: trunk/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm (0 => 284822)
--- trunk/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm (rev 0)
+++ trunk/Source/WebCore/platform/mac/PlatformSpeechSynthesizerMac.mm 2021-10-25 21:32:05 UTC (rev 284822)
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2013-2021 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. ``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
+ * 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 "PlatformSpeechSynthesizer.h"
+
+#if ENABLE(SPEECH_SYNTHESIS) && PLATFORM(MAC)
+
+#import "PlatformSpeechSynthesisUtterance.h"
+#import "PlatformSpeechSynthesisVoice.h"
+#import <AppKit/NSSpeechSynthesizer.h>
+#import <pal/spi/mac/SpeechSynthesisSPI.h>
+#import <wtf/RetainPtr.h>
+
+@interface WebSpeechSynthesisWrapper : NSObject<NSSpeechSynthesizerDelegate>
+{
+ WebCore::PlatformSpeechSynthesizer* m_synthesizerObject;
+ // Hold a Ref to the utterance so that it won't disappear until the synth is done with it.
+ WebCore::PlatformSpeechSynthesisUtterance* m_utterance;
+
+ RetainPtr<NSSpeechSynthesizer> m_synthesizer;
+ float m_basePitch;
+}
+
+- (WebSpeechSynthesisWrapper *)initWithSpeechSynthesizer:(WebCore::PlatformSpeechSynthesizer *)synthesizer;
+- (void)speakUtterance:(WebCore::PlatformSpeechSynthesisUtterance *)utterance;
+
+@end
+
+@implementation WebSpeechSynthesisWrapper
+
+- (WebSpeechSynthesisWrapper *)initWithSpeechSynthesizer:(WebCore::PlatformSpeechSynthesizer *)synthesizer
+{
+ if (!(self = [super init]))
+ return nil;
+
+ m_synthesizerObject = synthesizer;
+ [self updateBasePitchForSynthesizer];
+ return self;
+}
+
+// NSSpeechSynthesizer expects a Words per Minute (WPM) rate. There is no preset default
+// but they recommend that normal speaking is 180-220 WPM
+- (float)convertRateToWPM:(float)rate
+{
+ // We'll say 200 WPM is the default 1x value.
+ return 200.0f * rate;
+}
+
+- (float)convertPitchToNSSpeechValue:(float)pitch
+{
+ // This allows the base pitch to range from 0% - 200% of the normal pitch.
+ return m_basePitch * pitch;
+}
+
+- (void)updateBasePitchForSynthesizer
+{
+ // Reset the base pitch whenever we change voices, since the base pitch is different for each voice.
+ [m_synthesizer setObject:nil forProperty:NSSpeechResetProperty error:nil];
+ m_basePitch = [[m_synthesizer objectForProperty:NSSpeechPitchBaseProperty error:nil] floatValue];
+}
+
+- (void)speakUtterance:(WebCore::PlatformSpeechSynthesisUtterance *)utterance
+{
+ // When speak is called we should not have an existing speech utterance outstanding.
+ ASSERT(!m_utterance);
+ ASSERT(utterance);
+
+ if (!m_synthesizer) {
+ m_synthesizer = adoptNS([[NSSpeechSynthesizer alloc] initWithVoice:nil]);
+ [m_synthesizer setDelegate:self];
+ }
+
+ // Find if we should use a specific voice based on the voiceURI in utterance.
+ // Otherwise, find the voice that matches the language. The Mac doesn't have a default voice per language, so the first
+ // one will have to do.
+
+ WebCore::PlatformSpeechSynthesisVoice* utteranceVoice = utterance->voice();
+ // If no voice was specified, try to match by language.
+ if (!utteranceVoice && !utterance->lang().isEmpty()) {
+ for (auto& voice : m_synthesizerObject->voiceList()) {
+ if (equalIgnoringASCIICase(utterance->lang(), voice->lang())) {
+ utteranceVoice = voice.get();
+ if (voice->isDefault())
+ break;
+ }
+ }
+ }
+
+ NSString *voiceURI = nil;
+ if (utteranceVoice)
+ voiceURI = utteranceVoice->voiceURI();
+ else
+ voiceURI = [NSSpeechSynthesizer defaultVoice];
+
+ // Don't set the voice unless necessary. There's a bug in NSSpeechSynthesizer such that
+ // setting the voice for the first time will cause the first speechDone callback to report it was unsuccessful.
+ BOOL updatePitch = NO;
+ if (![[m_synthesizer voice] isEqualToString:voiceURI]) {
+ [m_synthesizer setVoice:voiceURI];
+ // Reset the base pitch whenever we change voices.
+ updatePitch = YES;
+ }
+
+ if (m_basePitch == 0 || updatePitch)
+ [self updateBasePitchForSynthesizer];
+
+ [m_synthesizer setObject:[NSNumber numberWithFloat:[self convertPitchToNSSpeechValue:utterance->pitch()]] forProperty:NSSpeechPitchBaseProperty error:nil];
+ [m_synthesizer setRate:[self convertRateToWPM:utterance->rate()]];
+ [m_synthesizer setVolume:utterance->volume()];
+
+ m_utterance = utterance;
+ [m_synthesizer startSpeakingString:utterance->text()];
+ m_synthesizerObject->client()->didStartSpeaking(*m_utterance);
+}
+
+- (void)pause
+{
+ if (!m_utterance)
+ return;
+
+ [m_synthesizer pauseSpeakingAtBoundary:NSSpeechImmediateBoundary];
+ m_synthesizerObject->client()->didPauseSpeaking(*m_utterance);
+}
+
+- (void)resume
+{
+ if (!m_utterance)
+ return;
+
+ [m_synthesizer continueSpeaking];
+ m_synthesizerObject->client()->didResumeSpeaking(*m_utterance);
+}
+
+- (void)cancel
+{
+ if (!m_utterance)
+ return;
+
+ [m_synthesizer stopSpeakingAtBoundary:NSSpeechImmediateBoundary];
+ m_synthesizerObject->client()->speakingErrorOccurred(*m_utterance);
+ m_utterance = 0;
+}
+
+- (void)invalidate
+{
+ m_utterance = 0;
+ [m_synthesizer setDelegate:nil];
+ [m_synthesizer stopSpeakingAtBoundary:NSSpeechImmediateBoundary];
+}
+
+- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking
+{
+ if (!m_utterance)
+ return;
+
+ UNUSED_PARAM(sender);
+
+ // Clear the m_utterance variable in case finish speaking kicks off a new speaking job immediately.
+ WebCore::PlatformSpeechSynthesisUtterance* utterance = m_utterance;
+ m_utterance = 0;
+
+ if (finishedSpeaking)
+ m_synthesizerObject->client()->didFinishSpeaking(*utterance);
+ else
+ m_synthesizerObject->client()->speakingErrorOccurred(*utterance);
+}
+
+- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender willSpeakWord:(NSRange)characterRange ofString:(NSString *)string
+{
+ UNUSED_PARAM(sender);
+ UNUSED_PARAM(string);
+
+ if (!m_utterance)
+ return;
+
+ // Mac platform only supports word boundaries.
+ m_synthesizerObject->client()->boundaryEventOccurred(*m_utterance, WebCore::SpeechBoundary::SpeechWordBoundary, characterRange.location);
+}
+
+@end
+
+namespace WebCore {
+
+PlatformSpeechSynthesizer::PlatformSpeechSynthesizer(PlatformSpeechSynthesizerClient* client)
+ : m_speechSynthesizerClient(client)
+{
+}
+
+PlatformSpeechSynthesizer::~PlatformSpeechSynthesizer()
+{
+ [m_platformSpeechWrapper invalidate];
+}
+
+static RetainPtr<CFArrayRef> speechSynthesisGetVoiceIdentifiers()
+{
+ // Get all the voices offered by TTS.
+ // By default speech only returns "premium" voices, which does not include all the
+ // international voices. This allows us to offer speech synthesis for all supported languages.
+ return adoptCF(CopySpeechSynthesisVoicesForMode((__bridge CFArrayRef)@[ @"VoiceGroupDefault", @"VoiceGroupCompact" ]));
+}
+
+static RetainPtr<CFStringRef> speechSynthesisGetDefaultVoiceIdentifierForLocale(NSLocale *userLocale)
+{
+ if (!userLocale)
+ return nil;
+
+#if HAVE(SPEECHSYNTHESIS_MONTEREY_SPI)
+ return adoptCF(CopyIdentifierStringForPreferredVoiceInListWithLocale(speechSynthesisGetVoiceIdentifiers().get(), (__bridge CFLocaleRef)userLocale));
+#else
+ return GetIdentifierStringForPreferredVoiceInListWithLocale(speechSynthesisGetVoiceIdentifiers().get(), (__bridge CFLocaleRef)userLocale);
+#endif
+}
+
+void PlatformSpeechSynthesizer::initializeVoiceList()
+{
+ auto availableVoices = speechSynthesisGetVoiceIdentifiers();
+ NSUInteger count = [(__bridge NSArray *)availableVoices.get() count];
+ for (NSUInteger k = 0; k < count; k++) {
+ NSString *voiceName = [(__bridge NSArray *)availableVoices.get() objectAtIndex:k];
+ NSDictionary *attributes = [NSSpeechSynthesizer attributesForVoice:voiceName];
+
+ NSString *voiceURI = [attributes objectForKey:NSVoiceIdentifier];
+ NSString *name = [attributes objectForKey:NSVoiceName];
+ NSString *language = [attributes objectForKey:NSVoiceLocaleIdentifier];
+ auto defaultVoiceURI = speechSynthesisGetDefaultVoiceIdentifierForLocale(adoptNS([[NSLocale alloc] initWithLocaleIdentifier:language]).get());
+
+ // Change to BCP-47 format as defined by spec.
+ language = [language stringByReplacingOccurrencesOfString:@"_" withString:@"-"];
+
+ bool isDefault = [(__bridge NSString *)defaultVoiceURI.get() isEqualToString:voiceURI];
+
+ m_voiceList.append(PlatformSpeechSynthesisVoice::create(voiceURI, name, language, true, isDefault));
+ }
+}
+
+void PlatformSpeechSynthesizer::pause()
+{
+ [m_platformSpeechWrapper pause];
+}
+
+void PlatformSpeechSynthesizer::resume()
+{
+ [m_platformSpeechWrapper resume];
+}
+
+void PlatformSpeechSynthesizer::speak(RefPtr<PlatformSpeechSynthesisUtterance>&& utterance)
+{
+ if (!m_platformSpeechWrapper)
+ m_platformSpeechWrapper = adoptNS([[WebSpeechSynthesisWrapper alloc] initWithSpeechSynthesizer:this]);
+
+ [m_platformSpeechWrapper speakUtterance:utterance.get()];
+}
+
+void PlatformSpeechSynthesizer::cancel()
+{
+ [m_platformSpeechWrapper cancel];
+}
+
+void PlatformSpeechSynthesizer::resetState()
+{
+ [m_platformSpeechWrapper cancel];
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SPEECH_SYNTHESIS) && PLATFORM(MAC)