From 671fa2a5eef47996aa8e38076be81793ff4d3a43 Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Fri, 15 May 2020 20:47:27 +1200 Subject: [PATCH] Improve fallbacks for missing markers. --- src/CExports.hs | 19 +++++++++++++++++++ src/main.c | 33 ++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/CExports.hs b/src/CExports.hs index e28efa9..b755683 100644 --- a/src/CExports.hs +++ b/src/CExports.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE OverloadedStrings #-} module CExports where import Types @@ -5,6 +6,10 @@ import Network.URI.Fetch (Session) import Render (c_renderDoc) import Links (c_extractLinks) +import qualified Text.XML as XML +import qualified Data.Text as Txt +import qualified Data.Text.Lazy as Txt (fromStrict) +import qualified Data.Map as M -- Types I can export to C import Foreign.StablePtr @@ -42,3 +47,17 @@ c_docLinksAndRendering c_session c_page rewriteUrls = do nil <- newCString "" links <- peekArray0 nil c_links newArray0 nil (ssml : links) + +-- Since I have XML Conduit here... +ssmlHasMark :: Txt.Text -> XML.Element -> Bool +ssmlHasMark ident (XML.Element "mark" attrs _) = Just ident == M.lookup "name" attrs +ssmlHasMark ident (XML.Element _ _ childs) = or [ssmlHasMark ident el | XML.NodeElement el <- childs] + +foreign export ccall c_ssmlHasMark :: CString -> CString -> IO Bool + +c_ssmlHasMark c_ident c_ssml = do + ident <- peekCString c_ident + ssml <- peekCString c_ssml + case XML.parseText XML.def $ Txt.fromStrict $ Txt.pack ssml of + Left _ -> return False + Right doc -> return $ ssmlHasMark (Txt.pack ident) $ XML.documentRoot doc diff --git a/src/main.c b/src/main.c index b5ae611..25bae90 100644 --- a/src/main.c +++ b/src/main.c @@ -29,6 +29,7 @@ void c_freePage(struct page*); char *c_renderDoc(struct session*, struct page*, _Bool); char **c_extractLinks(struct page*); char **c_docLinksAndRendering(struct session*, struct page*, _Bool); // FIXME segfaults. +int c_ssmlHasMark(char*, char*); /* espeak-ng integration. Based on the espeak-ng command source code. */ SNDFILE *fd_wav = NULL; @@ -123,10 +124,13 @@ int speak_initialize() { samplerate = espeak_ng_GetSampleRate(); return 0; } -void speak(char *ssml, char *mark) { +void speak(char *ssml, char *mark, char* fallback) { int flags = espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE | espeakCHARS_UTF8 | espeakSSML; - if (mark != NULL) espeak_Synth_Mark(ssml, strlen(ssml)+1, mark, 0, flags, NULL, NULL); - espeak_Synth(ssml, strlen(ssml)+1, 0, POS_CHARACTER, 0, flags, NULL, NULL); // FIXME only do so if mark doesn't play. + if (mark != NULL && c_ssmlHasMark(mark, ssml)) + espeak_Synth_Mark(ssml, strlen(ssml)+1, mark, 0, flags, NULL, NULL); + else if (fallback != NULL) + espeak_Synth_Mark(ssml, strlen(ssml)+1, fallback, 0, flags, NULL, NULL); + else espeak_Synth(ssml, strlen(ssml)+1, 0, POS_CHARACTER, 0, flags, NULL, NULL); } int read_keyboard = 0; int speak_finalize(char *ssml) { @@ -134,6 +138,7 @@ int speak_finalize(char *ssml) { char c = getc(stdin); if (c == '\033') { char mark[200]; + char fallback[200]; espeak_Cancel(); c = getc(stdin); if (c == 0 || c == -1 || c == '\033' || c == 'q') goto close; // skip [ @@ -144,37 +149,39 @@ int speak_finalize(char *ssml) { tablerow--; if (tablerow > 0) { sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol); - speak(ssml, mark); + speak(ssml, mark, NULL); break; } else in_table = 0; } section_no--; sprintf(mark, "-rhaps-section%i", section_no); - speak(ssml, section_no > 0 ? mark : NULL); + speak(ssml, section_no > 0 ? mark : NULL, NULL); break; case 'B': // 🠗 if (in_table) { tablerow++; sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol); - speak(ssml, mark); + sprintf(fallback, "-rhaps-section%i", section_no+1); + speak(ssml, mark, fallback); break; // FIXME What if that mark doesn't exist? } section_no++; sprintf(mark, "-rhaps-section%i", section_no); - speak(ssml, section_no > 0 ? mark : NULL); + speak(ssml, section_no > 0 ? mark : NULL, NULL); break; case 'C': // ➔ if (in_table) { tablecol++; sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol); - speak(ssml, mark); + sprintf(fallback, "-rhaps-paragraph%i", paragraph_no+1); + speak(ssml, mark, fallback); break; // FIXME What if that mark doesn't exist? } paragraph_no++; sprintf(mark, "-rhaps-paragraph%i", paragraph_no); - speak(ssml, paragraph_no > 0 ? mark : NULL); + speak(ssml, paragraph_no > 0 ? mark : NULL, NULL); break; case 'D': // 🠔 @@ -182,13 +189,13 @@ int speak_finalize(char *ssml) { tablecol--; if (tablecol > 0) { sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol); - speak(ssml, mark); + speak(ssml, mark, NULL); break; } else in_table = 0; } paragraph_no--; sprintf(mark, "-rhaps-paragraph%i", paragraph_no); - speak(ssml, paragraph_no > 0 ? mark : NULL); + speak(ssml, paragraph_no > 0 ? mark : NULL, NULL); break; } } @@ -303,7 +310,7 @@ int main(int argc, char **argv) { if (use_espeak) speak_err = speak_initialize(); char *ssml; for (int i = optind; i < argc; i++) { - if (use_espeak && speak_err == 0) speak(argv[i], NULL); + if (use_espeak && speak_err == 0) speak(argv[i], NULL, NULL); #ifdef WITH_SPEECHD else if (spd_conn != NULL) spd_say(spd_conn, SPD_MESSAGE, argv[i]); #endif @@ -315,7 +322,7 @@ int main(int argc, char **argv) { if (fd_ssml != NULL) fprintf(fd_ssml, "%s\n", ssml); if (fd_links != NULL) write_links(fd_links, links); - if (use_espeak & speak_err == 0) speak(ssml, "main"); + if (use_espeak & speak_err == 0) speak(ssml, "main", NULL); #ifdef WITH_SPEECHD if (spd_conn != NULL) spd_say(spd_conn, SPD_MESSAGE, ssml); #endif -- 2.30.2