How do I get notified when NSSpeechSynthesizer finished speaking? - xamarin

I am using Xamarin.Mac, and I am writing a text to speech project.
In Xamarin.Mac, the class NSSpeechSynthesizer does not provide the event DidFinishSpeaking. May I know how I can get notified when the speaking is finished?
Thank you very much

NSSpeechSynthesizer provides a delegate in the form of an interface (INSSpeechSynthesizerDelegate) that contains the DidFinishSpeaking method:
public partial class ViewController : NSViewController, INSSpeechSynthesizerDelegate
{
~~~~~~
public override void ViewDidLoad()
{
base.ViewDidLoad();
var s = new NSSpeechSynthesizer(NSSpeechSynthesizer.DefaultVoice)
{
Delegate = this
};
s.StartSpeakingString("StackOverflow");
}
[Export("speechSynthesizer:didFinishSpeaking:")]
public void DidFinishSpeaking(NSSpeechSynthesizer sender, bool finishedSpeaking)
{
Console.WriteLine("Done speaking");
}
~~~~~~
}

Related

Delegate method `WKWebView CreateWebView` method is not getting called

I am using Xamarin (C#) code for a macOS app. I have created the WKWebView and have outlet, added Navigation and UI delegates and trying to open an URL.
The Navigation delegates methods are getting called, but not sure what am I missing that UI Delegates method is not getting called.
Any help / guidance what to look for, or what mistake I am doing here, please.
Here's the code and image of same:
public override void ViewDidLoad()
{
base.ViewDidLoad();
var url = new NSUrl("https://google.com");
var request = new NSMutableUrlRequest(url);
_webView.UIDelegate = new WebViewDelegate();
_webView.NavigationDelegate = new WebViewNavigationDelegate();
_webView.LoadRequest(request);
}
}
internal class WebViewDelegate : WKUIDelegate
{
public override WKWebView CreateWebView(WKWebView webView, WKWebViewConfiguration configuration, WKNavigationAction navigationAction, WKWindowFeatures windowFeatures)
{
Console.WriteLine("this doesn't reach");
return null;
}
}
internal class WebViewNavigationDelegate : WKNavigationDelegate
{
public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
Console.WriteLine("this prints");
}
}

MVVMCross 5.3.2 UWP: Where to Get IMvxWindowsFrame for MvxFormsUwpViewPresenter

I'm working out of the Xamarin Forms for MVVMCross 5 Solution Template and updated the packages to the latest version (5.3.2 for MVVMCross). Doing that changes some namespaces around particularly in the UWP project.
It seems that I need to resolve IMvxViewPresenter as MvxFormsUwpViewPresenter which takes a IMvxWindowsFrame as an argument. In the setup file method of Setup.cs there's a XamlControls.Frame rootFrame passed as an argument but I'm not sure if that's suppose to be cast somehow as IMvxWindowsFrame.
Where can you pull the object that implements IMvxWindowsFrame from or is there another way to turn the rootFrame into an IMvxWindowsFrame legitimately.
public class Setup : MvxFormsWindowsSetup
{
private readonly LaunchActivatedEventArgs _launchActivatedEventArgs;
public Setup(XamlControls.Frame rootFrame, LaunchActivatedEventArgs e) : base(rootFrame, e)
{
_launchActivatedEventArgs = e;
// Mvx.RegisterSingleton<IMvxWindowsFrame>(rootFrame);
}
protected override void InitializeFirstChance()
{
base.InitializeFirstChance();
Mvx.RegisterSingleton<Core.Services.ILocalizeService>(new Services.LocalizeService());
Mvx.RegisterSingleton<ISettings>(CrossSettings.Current);
Mvx.RegisterType<IMvxViewPresenter, MvxFormsUwpViewPresenter>();
}
protected override MvxFormsApplication CreateFormsApplication()
{
return new Core.FormsApp();
}
protected override IMvxApplication CreateApp()
{
return new Core.MvxApp();
}
protected override IMvxTrace CreateDebugTrace()
{
return new Core.DebugTrace();
}
}
public sealed partial class MainPage : WindowsPage
{
public MainPage()
{
this.InitializeComponent();
var start = Mvx.Resolve<IMvxAppStart>();
start.Start();
var presenter = Mvx.Resolve<IMvxViewPresenter>() as MvxFormsUwpViewPresenter;
LoadApplication(presenter.FormsApplication);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
}
EDIT: I've been looking more into the class MvxFormsWindowsSetup in the source code at https://github.com/MvvmCross/MvvmCross/blob/develop/MvvmCross-Forms/MvvmCross.Forms.Uwp/Platform/MvxFormsWindowsSetup.cs. It appears that in the method CreateViewPresenter that the IMvxViewPresenter is registered as a singleton with the MvxWrappedFrame already inside but by default the code does not resolve when calling var presenter = Mvx.Resolve() as MvxFormsUwpViewPresenter; in the windows page. Possible bug? Trying to see if I can resolve it myself.
Looks like it fails to resolve even if I put the code right after when Mvx is suppose to register the type / singleton
protected override IMvxWindowsViewPresenter CreateViewPresenter(IMvxWindowsFrame rootFrame)
{
var presenter = new MvxFormsUwpViewPresenter(rootFrame, FormsApplication);
Mvx.RegisterSingleton<IMvxFormsViewPresenter>(presenter);
var presenter2 = Mvx.GetSingleton<IMvxViewPresenter>() as MvxFormsUwpViewPresenter;
return presenter;
}
When updating to MvvmCross 5.3.2 for UWP, the presenter needs to resolve as IMvxFormsViewPresenter rather than IMvxViewPresenter. Change the interface type and it should load properly.
public MainPage()
{
this.InitializeComponent();
var start = Mvx.Resolve<IMvxAppStart>();
start.Start();
var presenter = Mvx.Resolve<IMvxFormsViewPresenter>() as MvxFormsUwpViewPresenter;
LoadApplication(presenter.FormsApplication);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}

Xamarin iOS WKWebView DidFinishNavigation and DidStartProvisionalNavigation not getting called

I am implementing WKWebView in iOS Xamarin and i want to do something when load start and load finish. I have implemented IWKNavigationDelegate and added the following functions but non of them gets called. Am i missing something
Class definition
public partial class MasterViewController : UIViewController,IScanSuccessCallback, IWKScriptMessageHandler, IWKNavigationDelegate
{ }
Navigation Delegate functions
public void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
Console.WriteLine ("DidFinishNavigation");
}
public void DidFailNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailNavigation");
}
public void DidFailProvisionalNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailProvisionalNavigation");
}
public void DidStartProvisionalNavigation( WKWebView webView, WKNavigation navigation )
{
// When navigation starts, this gets called
Console.WriteLine("DidStartProvisionalNavigation");
}
complementing Jason's answer.
You are missing the required ExportAttribute for optional delegate methods, Xamarin Studio auto completion engine should generate this for you each time you implement any IFooInterface when Foo is an ObjC delegate and you type override (it should list optional and not optional members). ExportAttribute is only required for optional members (non abstract members in the c# interface).
In this particular case all members of WKNavigationDelegate ObjC protocol are optional so you need the Export attribute and the ObjC selector as its parameter.
You need to add using Foundation to your using statements, ExportAttribute is inside it.
[Export ("webView:didFinishNavigation:")]
public void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
Console.WriteLine ("DidFinishNavigation");
}
[Export ("webView:didFailNavigation:withError:")
public void DidFailNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailNavigation");
}
[Export ("webView:didFailProvisionalNavigation:withError:")]
public void DidFailProvisionalNavigation( WKWebView webView, WKNavigation navigation, NSError error )
{
// If navigation fails, this gets called
Console.WriteLine("DidFailProvisionalNavigation");
}
[Export ("webView:didStartProvisionalNavigation:")]
public void DidStartProvisionalNavigation( WKWebView webView, WKNavigation navigation )
{
// When navigation starts, this gets called
Console.WriteLine("DidStartProvisionalNavigation");
}
Hope this helps.
You need to explicitly assign the NavigationDelegate class to webview
WKWebView web = new WKWebView();
// if the current class implements IWKNavigationDelegate, you can do this
web.NavigationDelegate = this;
// or you can create a separate class that implements IWKNavigationDelegate
web.NavigationDelegate = new MyWebDelegate();

Handle a MonoMac Exit/Window Close Event

Similar to this question I posted earlier: Handle a WPF Exit Event
I found a solution in Objective C, but I'm not familiar with how to port this with Mono.
EDIT
I found that I could use the following override to do what I wanted to:
NSApplicationTerminateReply ApplicationShouldTerminate (NSApplication sender)
However, there is a problem now if I close my MainWindow since that is actually where I want to start calling application exit. I already have an override for ApplicationShouldTerminateAfterLastWindowClosed that returns true, so the terminate override is being called correctly. But when I'm returning Cancel, the app is running, sans window. Is there a way to intercept the window closing event?
This is what I ended up doing. I created a new class called MainWindowDelegate:
public class MainWindowDelegate : MonoMac.AppKit.NSWindowDelegate
{
public override WindowShouldClose (MonoMac.Foundation.NSObject sender)
{
return false;
}
}
Then, in my MainWindowController class:
public class MainWindowController
{
private MainWindowDelegate _delegate;
// Shared initialization code
void Initialize()
{
_delegate = new MainWindowDelegate();
}
public override void WindowDidLoad()
{
Window.Delegate = _delegate;
}
}

How to quit MonoMac app when window closes?

I can use - (BOOL)applicationShouldTerminateAfterLastWindowClosed: method to quit cocoa app when window closes by using the method in application's delegate.
How can I do the same thing with MonoMac? In general, how can I map objective-c method to MonoMac's C# function?
I found this code, I see that I can use the same function in the delegate.
namespace AnimatingViews
{
public partial class AppDelegate : NSApplicationDelegate
{
AnimatingViewsWindowController animatingViewsWindowController;
public AppDelegate ()
{
}
public override void FinishedLaunching (NSObject notification)
{
animatingViewsWindowController = new AnimatingViewsWindowController ();
animatingViewsWindowController.Window.MakeKeyAndOrderFront (this);
}
public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender)
{
return true;
}
}
}

Resources