vlc | branch: master | Felix Paul Kühne <[email protected]> | Wed Jul 29 20:11:00 2015 +0200| [7ea5c465d01551059c3168802fb2f7b76a8d0dfe] | committer: Felix Paul Kühne
text renderer: add basic text to speech synthesis for OS X (#11893) > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7ea5c465d01551059c3168802fb2f7b76a8d0dfe --- modules/text_renderer/Makefile.am | 6 + modules/text_renderer/nsspeechsynthesizer.m | 160 +++++++++++++++++++++++++++ po/POTFILES.in | 1 + 3 files changed, 167 insertions(+) diff --git a/modules/text_renderer/Makefile.am b/modules/text_renderer/Makefile.am index d41bc6d..43ccb67 100644 --- a/modules/text_renderer/Makefile.am +++ b/modules/text_renderer/Makefile.am @@ -36,6 +36,12 @@ libquartztext_plugin_la_LDFLAGS = $(AM_LDLFAGS) -rpath '$(textdir)' \ EXTRA_LTLIBRARIES += libquartztext_plugin.la text_LTLIBRARIES += $(LTLIBquartztext) +if HAVE_OSX +libnsspeechsynthesizer_plugin_la_SOURCES = text_renderer/nsspeechsynthesizer.m +libnsspeechsynthesizer_plugin_la_LDFLAGS = -Wl,-framework,Cocoa +text_LTLIBRARIES += libnsspeechsynthesizer_plugin.la +endif + libsvg_plugin_la_SOURCES = text_renderer/svg.c libsvg_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(SVG_CFLAGS) libsvg_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(textdir)' diff --git a/modules/text_renderer/nsspeechsynthesizer.m b/modules/text_renderer/nsspeechsynthesizer.m new file mode 100644 index 0000000..47101f0 --- /dev/null +++ b/modules/text_renderer/nsspeechsynthesizer.m @@ -0,0 +1,160 @@ +/***************************************************************************** + * nsspeechsynthesizer.m: Simple text to Speech renderer for Mac OS X + ***************************************************************************** + * Copyright (C) 2015 VLC authors and VideoLAN + * $Id$ + * + * Authors: Felix Paul Kühne <fkuehne # videolan # org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_common.h> +#include <vlc_plugin.h> +#include <vlc_filter.h> + +#import <Cocoa/Cocoa.h> + +static int Create (vlc_object_t *); +static void Destroy(vlc_object_t *); +static int RenderText(filter_t *, + subpicture_region_t *, + subpicture_region_t *, + const vlc_fourcc_t *); + +vlc_module_begin () +set_description(N_("Speech synthesis for Mac OS X")) +set_category(CAT_VIDEO) +set_subcategory(SUBCAT_VIDEO_SUBPIC) + +set_capability("text renderer", 50) +set_callbacks(Create, Destroy) +vlc_module_end () + +struct filter_sys_t +{ + NSSpeechSynthesizer *speechSynthesizer; + NSString *currentLocale; + NSString *lastString; +}; + +static int Create (vlc_object_t *p_this) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_sys_t *p_sys; + + p_filter->p_sys = p_sys = malloc(sizeof(filter_sys_t)); + if (!p_sys) + return VLC_ENOMEM; + + p_sys->currentLocale = p_sys->lastString = @""; + p_sys->speechSynthesizer = [[NSSpeechSynthesizer alloc] init]; + + p_filter->pf_render = RenderText; + + return VLC_SUCCESS; +} + +static void Destroy(vlc_object_t *p_this) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_sys_t *p_sys = p_filter->p_sys; + + [p_sys->speechSynthesizer stopSpeaking]; + [p_sys->speechSynthesizer release]; + p_sys->speechSynthesizer = nil; + + [p_sys->lastString release]; + p_sys->lastString = nil; + + [p_sys->currentLocale release]; + p_sys->currentLocale = nil; + + free(p_sys); +} + +static NSString * languageCodeForString(NSString *string) { + return (NSString *)CFStringTokenizerCopyBestStringLanguage((CFStringRef)string, CFRangeMake(0, [string length])); +} + +static int RenderText(filter_t *p_filter, + subpicture_region_t *p_region_out, + subpicture_region_t *p_region_in, + const vlc_fourcc_t *p_chroma_list) +{ + @autoreleasepool { + filter_sys_t *p_sys = p_filter->p_sys; + text_segment_t *p_segment = p_region_in->p_text; + + if (!p_segment) + return VLC_EGENERIC; + + for ( const text_segment_t *s = p_segment; s != NULL; s = s->p_next ) { + if ( !s->psz_text ) + continue; + + if (strlen(s->psz_text) == 0) + continue; + + NSString *stringToSpeech = [NSString stringWithUTF8String:s->psz_text]; + + if ([p_sys->lastString isEqualToString:stringToSpeech]) + continue; + + if ([stringToSpeech isEqualToString:@"\n"]) + continue; + + p_sys->lastString = [stringToSpeech retain]; + + msg_Dbg(p_filter, "Speaking '%s'", [stringToSpeech UTF8String]); + + NSString *detectedLocale = languageCodeForString(stringToSpeech); + if (detectedLocale != nil) { + if (![detectedLocale isEqualToString:p_sys->currentLocale]) { + p_sys->currentLocale = [detectedLocale retain]; + msg_Dbg(p_filter, "switching speaker locale to '%s'", [p_sys->currentLocale UTF8String]); + NSArray *voices = [NSSpeechSynthesizer availableVoices]; + NSUInteger count = voices.count; + NSRange range = NSMakeRange(0, 2); + + for (NSUInteger i = 0; i < count; i++) { + NSDictionary *voiceAttributes = [NSSpeechSynthesizer attributesForVoice:voices[i]]; + NSString *voiceLanguage = voiceAttributes[@"VoiceLanguage"]; + if ([p_sys->currentLocale isEqualToString:[voiceLanguage substringWithRange:range]]) { + NSString *voiceName = voiceAttributes[@"VoiceName"]; + msg_Dbg(p_filter, "switched to voice '%s'", [voiceName UTF8String]); + if ([voiceName isEqualToString:@"Agnes"] || [voiceName isEqualToString:@"Albert"]) + continue; + [p_sys->speechSynthesizer setVoice:voices[i]]; + break; + } + } + } + } + + [p_sys->speechSynthesizer startSpeakingString:stringToSpeech]; + } + + return VLC_SUCCESS; + } +} diff --git a/po/POTFILES.in b/po/POTFILES.in index 2e7245d..9f728d9 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1059,6 +1059,7 @@ modules/stream_out/stats.c modules/stream_out/standard.c modules/stream_out/transcode/transcode.c modules/text_renderer/freetype.c +modules/text_renderer/nsspeechsynthesizer.m modules/text_renderer/quartztext.c modules/text_renderer/svg.c modules/text_renderer/tdummy.c _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
