[vlc-commits] text renderer: add basic text to speech synthesis for OS X (#11893)
Felix Paul Kühne
git at videolan.org
Wed Jul 29 20:15:01 CEST 2015
vlc | branch: master | Felix Paul Kühne <fkuehne at videolan.org> | 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
More information about the vlc-commits
mailing list