UWP tweaks and optimizations.

* Initialized TTS `MediaPlayer` in real-time mode.
* Set media category to speech.
* More aggressively drop locks to prevent deadlocks.
* Remove checks of queued items that are no longer necessary.
* Made `is_speaking` check both media player state and queued item count.
* Return eagerly from `stop` if speech isn't in progress, thus eliminating more locks.
This commit is contained in:
Nolan Darilek 2020-11-25 10:07:28 -06:00
parent 728c409e25
commit f4952ad132
1 changed files with 14 additions and 11 deletions

View File

@ -8,7 +8,7 @@ use winrt::*;
use tts_winrt_bindings::windows::media::playback::{ use tts_winrt_bindings::windows::media::playback::{
CurrentMediaPlaybackItemChangedEventArgs, MediaPlaybackItem, MediaPlaybackList, CurrentMediaPlaybackItemChangedEventArgs, MediaPlaybackItem, MediaPlaybackList,
MediaPlaybackState, MediaPlayer, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory,
}; };
use tts_winrt_bindings::windows::media::speech_synthesis::SpeechSynthesizer; use tts_winrt_bindings::windows::media::speech_synthesis::SpeechSynthesizer;
use tts_winrt_bindings::windows::{foundation::TypedEventHandler, media::core::MediaSource}; use tts_winrt_bindings::windows::{foundation::TypedEventHandler, media::core::MediaSource};
@ -53,12 +53,16 @@ impl WinRT {
info!("Initializing WinRT backend"); info!("Initializing WinRT backend");
let playback_list = MediaPlaybackList::new()?; let playback_list = MediaPlaybackList::new()?;
let player = MediaPlayer::new()?; let player = MediaPlayer::new()?;
player.set_real_time_playback(true)?;
player.set_audio_category(MediaPlayerAudioCategory::Speech)?;
player.set_source(&playback_list)?; player.set_source(&playback_list)?;
let mut backend_id = NEXT_BACKEND_ID.lock().unwrap(); let mut backend_id = NEXT_BACKEND_ID.lock().unwrap();
let bid = BackendId::WinRT(*backend_id); let bid = BackendId::WinRT(*backend_id);
*backend_id += 1; *backend_id += 1;
drop(backend_id);
let mut backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap(); let mut backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
backend_to_media_player.insert(bid, player.clone()); backend_to_media_player.insert(bid, player.clone());
drop(backend_to_media_player);
player.media_ended(TypedEventHandler::new(|sender: &MediaPlayer, _args| { player.media_ended(TypedEventHandler::new(|sender: &MediaPlayer, _args| {
let source = sender.source()?; let source = sender.source()?;
let source: MediaPlaybackList = source.try_into()?; let source: MediaPlaybackList = source.try_into()?;
@ -80,6 +84,7 @@ impl WinRT {
}))?; }))?;
let mut backend_to_playback_list = BACKEND_TO_PLAYBACK_LIST.lock().unwrap(); let mut backend_to_playback_list = BACKEND_TO_PLAYBACK_LIST.lock().unwrap();
backend_to_playback_list.insert(bid, playback_list.clone()); backend_to_playback_list.insert(bid, playback_list.clone());
drop(backend_to_playback_list);
playback_list.current_item_changed(TypedEventHandler::new( playback_list.current_item_changed(TypedEventHandler::new(
|sender: &MediaPlaybackList, args: &CurrentMediaPlaybackItemChangedEventArgs| { |sender: &MediaPlaybackList, args: &CurrentMediaPlaybackItemChangedEventArgs| {
let backend_to_playback_list = BACKEND_TO_PLAYBACK_LIST.lock().unwrap(); let backend_to_playback_list = BACKEND_TO_PLAYBACK_LIST.lock().unwrap();
@ -155,17 +160,11 @@ impl Backend for WinRT {
let content_type = stream.content_type()?; let content_type = stream.content_type()?;
let source = MediaSource::create_from_stream(stream, content_type)?; let source = MediaSource::create_from_stream(stream, content_type)?;
let item = MediaPlaybackItem::create(source)?; let item = MediaPlaybackItem::create(source)?;
let item_index = self.playback_list.current_item_index()?; if interrupt && self.is_speaking()? {
let item_count = self.playback_list.items()?.size()?;
let state = self.player.playback_session()?.playback_state()?;
if interrupt && state != MediaPlaybackState::Paused {
self.stop()?; self.stop()?;
} }
if state == MediaPlaybackState::Paused && item_index != 0 && item_index < item_count {
self.playback_list.items()?.clear()?;
}
self.playback_list.items()?.append(&item)?; self.playback_list.items()?.append(&item)?;
if !self.is_speaking()? { if self.player.playback_session()?.playback_state()? != MediaPlaybackState::Playing {
self.player.play()?; self.player.play()?;
} }
let mut uid = NEXT_UTTERANCE_ID.lock().unwrap(); let mut uid = NEXT_UTTERANCE_ID.lock().unwrap();
@ -179,10 +178,13 @@ impl Backend for WinRT {
fn stop(&mut self) -> std::result::Result<(), Error> { fn stop(&mut self) -> std::result::Result<(), Error> {
trace!("stop()"); trace!("stop()");
if !self.is_speaking()? {
return Ok(());
}
self.playback_list.items()?.clear()?; self.playback_list.items()?.clear()?;
let mut mappings = UTTERANCE_MAPPINGS.lock().unwrap();
let mut callbacks = CALLBACKS.lock().unwrap(); let mut callbacks = CALLBACKS.lock().unwrap();
let callbacks = callbacks.get_mut(&self.id).unwrap(); let callbacks = callbacks.get_mut(&self.id).unwrap();
let mut mappings = UTTERANCE_MAPPINGS.lock().unwrap();
if let Some(callback) = callbacks.utterance_stop.as_mut() { if let Some(callback) = callbacks.utterance_stop.as_mut() {
for mapping in &*mappings { for mapping in &*mappings {
callback(mapping.2); callback(mapping.2);
@ -259,9 +261,10 @@ impl Backend for WinRT {
} }
fn is_speaking(&self) -> std::result::Result<bool, Error> { fn is_speaking(&self) -> std::result::Result<bool, Error> {
let item_count = self.playback_list.items()?.size()?;
let state = self.player.playback_session()?.playback_state()?; let state = self.player.playback_session()?.playback_state()?;
let playing = state == MediaPlaybackState::Playing; let playing = state == MediaPlaybackState::Playing;
Ok(playing) Ok(item_count != 0 || playing)
} }
} }