diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 16c7f08..0000000 --- a/.clang-format +++ /dev/null @@ -1,41 +0,0 @@ ---- -Language: Cpp -BasedOnStyle: LLVM - -AlignAfterOpenBracket: Align -AlignEscapedNewlines: Left -AlignOperands: AlignAfterOperator -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortEnumsOnASingleLine: false -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -BinPackArguments: true -BinPackParameters: true -BreakBeforeBraces: Linux -ColumnLimit: 80 -IndentPPDirectives: BeforeHash -IndentWidth: 4 -InsertTrailingCommas: None -KeepEmptyLinesAtTheStartOfBlocks: false -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SpaceAfterCStyleCast: true -SpaceAfterLogicalNot: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceAroundPointerQualifiers: Before -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 5 -TabWidth: 4 -UseTab: AlignWithSpaces -... diff --git a/.gitignore b/.gitignore index 1b2211d..7870fbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -build* +espeakup +*.d +*.o +*.swp diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..b276f00 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1806 @@ +commit 2964310b2411c10756712ba902687e8388c78142 +Author: William Hubbs +Commit: William Hubbs + + makefile: add target to generate changelog + +commit 918e8853cdd8270c77f641c69871851effe18416 +Author: William Hubbs +Commit: William Hubbs + + version 0.80 + +commit 3e5815429bd702d9b0af68d793e6c83f035f9e23 +Author: William Hubbs +Commit: William Hubbs + + Add my email address to the copyright statement + +commit 8b49d9d211f917f7ee2009569f746659ec9096a8 +Author: Christopher Brannon +Commit: William Hubbs + + Fix implicit function declaration warning. + + This fixes #7 + +commit 97adab70de5e49dde3ac26774a636cbca48558c0 +Author: Christopher Brannon +Commit: William Hubbs + + Replace usage of daemon(3). + + Original patch and commit message courtesy of: + Samuel Thibault + + currently espeakup uses daemon() to do the daemonizing stuff. + Unfortunately, daemon() does things not very appropriately, and there + is notably a delay between the parent exit()ing and the child writing + the pid file. The attached patch reimplements it properly, espeakup + then notably plays much more nicely with systemd. + + Modified by Chris to apply to master. + This fixes #8. + +commit 92903254894d2b6f2c398a104e78d15553de6017 +Author: Christopher Brannon +Commit: William Hubbs + + Fix spelling keystrokes and char-by-char echo. + + Use ssml's interpret-as="characters" setting when the kernel reports + just one character. This allows the use of espeak's internationalized + spelling of letters instead of having to maintain spelling ourselves in speakup. + + Original patch courtesy of + Samuel Thibault + and modified to work with the current code by Chris. + + This fixes #6. + +commit ee099174d849e32bf7b555e458963d27f84c64b2 +Author: Samuel Thibault +Commit: William Hubbs + + Allow a voice to be selected by language name + + This allows the -V option on the command line to be a language name. + +commit c1ad891f2e321b052802a2c3c121522757948e61 +Author: Samuel Thibault +Commit: William Hubbs + + Create pid file when espeakup is really ready + + This makes sure that we do not report that we are ready until everything + is initialized. + +commit d97724373556e5ad6d632249bcc0ba4ef7aec4d8 +Author: Christopher Brannon +Commit: William Hubbs + + Add a missing #include, so that this can be built with musl. + + This closes #5. + +commit d95ee07775f6a63d80323e5ea242c530adf9c79b +Author: William Hubbs +Commit: William Hubbs + + Revert "add indexing support" + + This reverts commit e84e000b3ec9d393d720845a5f5fd05aa2ee7302. + I need to think more about how to implement this. + +commit e84e000b3ec9d393d720845a5f5fd05aa2ee7302 +Author: William Hubbs +Commit: William Hubbs + + add indexing support + +commit 3fbbdf19224c26b80b161666b37cec70ac5dd6d2 +Author: William Hubbs +Commit: William Hubbs + + Do not try to remove the pid file unless we are in speakup mode + +commit 58ed438f00c0f79c87885b73292c3b4e5c44e0d4 +Author: William Hubbs +Commit: William Hubbs + + rework two if statements + + These if statements were executing code if we were not in acsint mode. + They have been combined and the code is now executed when we are in + speakup mode, which is what we want. + +commit b2bd1d33a8a8d08ea9316bcf3cf8169545e7df78 +Author: William Hubbs +Commit: William Hubbs + + make espeakup's default rate closer to espeak's default + +commit 3b4b6d0cbc98d175f00a9f1e744406e3491c6d85 +Author: William Hubbs +Commit: William Hubbs + + change code to use allocMem wrapper for memory allocation + + One of the new string handling routines is a wrapper for allocating + memory. This commit changes the rest of the code to take advantage of + that wrapper. + +commit 6180ff6e49371d9fc1cfb5afb05941222d925d70 +Author: Christopher Brannon +Commit: Christopher Brannon + + Don't check to see if espeakup is running in acsint mode. + + This check is important when running with speakup, since there can only + be one instance accessing /dev/softsynth. + It is unnecessary in acsint mode. + +commit ba316a4cd4ad42b5cf7a550953c1dc26338e3569 +Author: William Hubbs +Commit: William Hubbs + + separate string handling routines into their own module + +commit c06f18c4544a6e9e3d28b8f037bc40588fbff3f5 +Author: Christopher Brannon +Commit: William Hubbs + + support adapters using the acsint module + +commit 70f74657c274d37f94cf7a4eabcd1d06bafbfcb5 +Author: William Hubbs +Commit: William Hubbs + + fix Makefile to use MANMODE to install man pages + +commit 999e6551b5999f5779299e51858e4bbb587f5561 +Author: William Hubbs +Commit: William Hubbs + + add pid path option to help + +commit 3353241a79f0e2b130dce5e98d656284a7da84f8 +Author: William Hubbs +Commit: William Hubbs + + add command line option to change the pid path + + This adds a -P or --pid-path option to the command line which + allows the user to change the path and the name of the pid file created + when espeakup is running as a daemon. + + I would like to thank Chris Brannon for the original idea for this. + +commit 49dcacb2eca6f808f1f52a4faaf96f1fae24e4b5 +Author: William Hubbs +Commit: William Hubbs + + adjust rate offset and multiplier for espeak 1.45.04 + +commit 2154d1a23157cc2b0ff72f1ed51e5c8a26b452cb +Author: William Hubbs +Commit: William Hubbs + + use memset to initialize sigaction structure + +commit 1990e8e25d23fd4cbaa924ac7af480e2a079b9dc +Author: Christopher Brannon +Commit: William Hubbs + + Properly initialize sigaction struct. + + The sigaction struct used in signal_thread was stored in an automatic + variable. The fields which were not set manually had undefined values. + +commit 701074fd9685ce4133672fbb35f046e76ab13422 +Author: William Hubbs +Commit: William Hubbs + + go back to just using a makefile + + The reason I went to autotools was the multiple sound systems, but since + we are now just using espeak's audio processing we can go back to a more + simple build system. + +commit 7bf2eee07a6c5d2120e62d13e0385e4c8e9c6782 +Author: William Hubbs +Commit: William Hubbs + + remove experimental alsa support + + The direct alsa support was experimental and never worked well. It had a + setting which was system specific. Also, I feel that it is better to let + espeak control the audio processing. + +commit c7ae47dfe59481b29ec80de2faaa6c8d3bd63379 +Author: William Hubbs +Commit: William Hubbs + + add experimental support for building a static binary + + This is done by adding a --enable-standalone switch to the configure + script. + +commit 3bfc662bae54038172de1c52b04e9c589d2f7bd0 +Author: William Hubbs +Commit: William Hubbs + + update location of latest version and git repository + +commit 037e6422179424dd40667765039c6584ac306514 +Author: William Hubbs +Commit: William Hubbs + + rename todo file + +commit 0d9d7b61419eb37247e8f7afb6c5b7ff198f0ab7 +Author: William Hubbs +Commit: William Hubbs + + update readme + +commit 056dcf70fe5a6850b73193ea06480bd955695e2e +Author: William Hubbs +Commit: William Hubbs + + convert to autotools + +commit d1630432ba55033c82da0dcae4a409f14da8d03f +Author: William Hubbs +Commit: William Hubbs + + re-organized the makefile. + +commit 8fda956e020abcde9365c20c6e14f3ebc15cd2e1 +Author: William Hubbs +Commit: William Hubbs + + fixed permissions in makefile + + It turns out that the install commands need to have the permission + options otherwise the permission of everything that is installed is 755, + which is not correct. + +commit 4cfcd7ba116ddd3e1c80744b4eb7e0b83438ec86 +Author: William Hubbs +Commit: William Hubbs + + fixed mandir + + the mandir variable in the makefile should point only to the top level + of the man tree. + +commit 1a10788c5f140f75e0f54a2baaf8625125bb52ac +Author: William Hubbs +Commit: William Hubbs + + lowered latency setting to 1/40 of a second. + +commit edb5e50fcd52d6f0ed9d2decb5c874dfd9395998 +Author: William Hubbs +Commit: William Hubbs + + make alsa code more readable + + This changes the code to use constants for the parameters to + snd_pcm_set_params. This makes it easier to read the code and to update + the values if needed. + +commit dec561324df67bd64eede09bcb2eb25273a04081 +Author: William Hubbs +Commit: William Hubbs + + updates to alsa support + + After studying pcm_min.c in the alsa library git repository, I updated + the alsa support to be similar to what I saw there. + +commit 486fe27f47d12a0482060aac4fc6c1568fab0613 +Author: William Hubbs +Commit: William Hubbs + + removed permission settings from makefile + +commit 311b6911959263a81f4dd74b44ad93af53a981b1 +Author: William Hubbs +Commit: William Hubbs + + fix makefile to not define variables if they are already defined + +commit ffe397fb911b0de8a14cacfc69bf9e683c9ef402 +Author: William Hubbs +Commit: William Hubbs + + removed the minimum function + + This function really wasn't needed. I also attempted to make the + callback functionn more like the test code in the alsa library git + repository. + +commit e66311bb992122ca4797eab1d2a79b1619c71b9b +Author: William Hubbs +Commit: William Hubbs + + added automatic dependency tracking to the Makefile + +commit 11cc053d822d563b9c040ce50341f8c8cd8b4f86 +Author: William Hubbs +Commit: William Hubbs + + reworked the makefile + + This version of the makefile should be more compatible with allowing + users to pass in cflags. + +commit 48fa03faf5529a4072ae50fe9ff983333bc6fca0 +Author: William Hubbs +Commit: William Hubbs + + renamed espeak_sound.c to portaudio.c + + This better describes the sound system that espeak uses natively. + +commit 654fc810fe981907d3f17d212ae51d9d6124fa42 +Author: William Hubbs +Commit: William Hubbs + + default prefix to /usr/local + + Without packaging, we should be installing espeakup in /usr/local. + +commit e4e3f0979e1820712a6a88bfcf60da34a8a747f0 +Author: William Hubbs +Commit: William Hubbs + + the status handle should be static + +commit 57547e8efa0dcf9f7f1750d7e8472f7207d20329 +Author: William Hubbs +Commit: William Hubbs + + renamed synth.c to espeak.c + + The name was changed because it describes the function of this code more + accurately. + +commit ac9e12414b2f4a1b38f8dabdaf7eb5ae33276008 +Author: William Hubbs +Commit: William Hubbs + + made stop_requested a global variable + + The two variables, stop_requested and runner_must_stop were performing + the same function, so I am using one variable, stop_requested for this + function. + +commit 18ebab3247934c71320abed559021fe6eebab530 +Author: William Hubbs +Commit: William Hubbs + + indentation fixes + +commit cc7e77eb9db904f27b9de12f4b25b17c2f6d5b02 +Author: William Hubbs +Commit: William Hubbs + + move stop_audio call to synth thread + + Since there is no reason currently for the softsynth thread to do this, + it makes better sense to have the synth thread control all interaction + with espeak. + +commit 32d848cb76de9853564d7e2ea37725c1f9af1ae4 +Author: William Hubbs +Commit: William Hubbs + + make callback honor should_run + + The callback should return and abort synthesis if should_run is 0. This + fixes slow shutdown times in alsa mode. + +commit 4de82bf24cff9e5a82a2645f30af0dbfae6ded05 +Author: William Hubbs +Commit: William Hubbs + + added a couple of #defines to the alsa code + +commit 739e074072100dd420b10eb1d8b8d55451b9bdea +Author: William Hubbs +Commit: William Hubbs + + reworked the queue_remove function + + Now, when queue_remove is called, it returns the pointer to the data of + the first entry in the queue and removes the entry. + +commit 014d27b7aa218db968ab19b2b493fe95406b4b8b +Author: William Hubbs +Commit: William Hubbs + + removed some unlock_audio_mutex() calls + +commit 82490a98d253d5201f93f309289346fff5169abc +Author: William Hubbs +Commit: William Hubbs + + call snd_pcm_prepare after snd_pcm_drop in stop_audio + +commit 101e14901e0517f6f09024dc8dc1f47dc682227a +Author: William Hubbs +Commit: William Hubbs + + removed white space in the makefile + +commit dc056e6c773e203af74d290393819b7fdc4043e0 +Author: William Hubbs +Commit: William Hubbs + + broke the queue definitions out into their own header file + +commit 0a9a8cce9bcb0310903aaffafd2dbdbe5a6458c4 +Author: William Hubbs +Commit: William Hubbs + + small style changes + +commit 40479540b4c8dd6a876b084bce0e6c806033da06 +Author: Christopher Brannon +Commit: William Hubbs + + Fix a memory leak. + + If we fail to add entries to the queue in queue_add_cmd or + queue_add_text, properly free the entry. + +commit ccb8cea91ee1537e24070dbd3cc568e6f24ddb28 +Author: William Hubbs +Commit: William Hubbs + + stop speech before clearing the queue + + Thanks to Kirk Reiser for pointing out that this makes the cancel + response faster. + +commit 31ad5f04ca691228889bd839852d8b19321c86c1 +Author: Christopher Brannon +Commit: William Hubbs + + Completely data-agnostic queue functions. + + The functions in queue.c no longer use static variables. We can now use + them for multiple queues, if necessary. + +commit 011ec271627615be44e1bacd6d269745c86028e9 +Author: Christopher Brannon +Commit: William Hubbs + + Create pipe before starting the signal handler thread. + + The thread can write to the pipe, so the pipe must be initialized + before the thread starts. + +commit 04d10d88ec0bb2161885bc3358a9bc6b5e06ce35 +Author: William Hubbs +Commit: William Hubbs + + more sound updates + + removed the user_data processing code and put the call to snd_pcm_drop + in stop_audio. + +commit ceaae3640a51fad408386f27bb30fe2063cdf58e +Author: William Hubbs +Commit: William Hubbs + + audio should be stopped in softsynth_thread not espeak_thread + +commit c9f871f687c6bd6ef1a562000c53c6762cfa7205 +Author: William Hubbs +Commit: William Hubbs + + see if we need to silence speech before we process the queue + +commit a82bbd81400cfa002835c35ce46a956cc81460ad +Author: William Hubbs +Commit: William Hubbs + + fixed a memory leak + + If we processed an entry from the queue successfully, we were removing + the entry itself from the queue but not freeing the memory allocated to + the entry. + +commit 58f09983f856703e8a06d9b16ef17b7d8728eb4d +Author: William Hubbs +Commit: William Hubbs + + fixed callback return code + + The callback should use the value of stop_requested as its return code. + +commit 0238baa5c29f9fef26b4608be24e4f63b2927e82 +Author: William Hubbs +Commit: William Hubbs + + more alsa updates + + Made an 'if' statement in the callback more clear and added some locking + for the audio mutex. + +commit bcd64cb263745e3994484156713a601db1b59990 +Author: William Hubbs +Commit: William Hubbs + + created a start_audio function + + This moves audio control to the specific files, espeak_sound.c and + alsa.c, which are tied to the sound systems. + +commit 9b7dcebb6d3dd84d19a448e7e79a1746cd939a62 +Author: William Hubbs +Commit: William Hubbs + + alsa updates + + The first while loop in the callback doesn't need to be a loop. If the + audio fails, we can just print an error and return. + +commit 46bf3d99d51960c7a179d9bfd6724c4a428e0658 +Author: William Hubbs +Commit: William Hubbs + + all access of the audio mutex should go through our functions + +commit 87ab6c6ea822f9f7b393d1cb83c9f579d728326a +Author: William Hubbs +Commit: William Hubbs + + make sure that snd_pcm_drop is successful. + + This was suggested by Kirk Reiser and Chris Brannon. + +commit 4889572ad18a8be877916d131d9a101b6563773c +Author: William Hubbs +Commit: William Hubbs + + use user_data to detect old events + + When espeak_Cancel is called, change the value of user_data that is + passed to the events, and, in the callback, use this to test to see if + cancel was received. If the value of user_data has changed, discarde + events that have the old value. This patch is from Chris Brannon. + +commit a9398bdeb413f8c9b88178756e0cdc7ede55b0bc +Author: William Hubbs +Commit: William Hubbs + + Added another error check for alsa + +commit be879d206b52221546e4b8e00b60e0c0cf70f855 +Author: William Hubbs +Commit: William Hubbs + + alsa update + + I changed the name of the callback to alsa_callback and removed a line + that was making the amount of data written to the sound card very small. + +commit c1d33d673838faf8b70cc42c72c119f5c0002d44 +Author: William Hubbs +Commit: William Hubbs + + Set the espeak audio buffer size to 50 ms + + This should help make the cancel command more responsive. + +commit 0471ff47f4dc031cf70b14eb15128fd60fb185dd +Author: William Hubbs +Commit: William Hubbs + + add support for the user_data parameter to espeak_synth + + The user_data parameter is just a pointer that is passed into the + espeak_synth call that is passed back to the callback. In native mode, + we are not using it since there is not a callback. However, in alsa + mode, it will be used to indicate when a cancel was processed. + +commit 520bbae36512731bc075870c0baa9339929b4fde +Author: William Hubbs +Commit: William Hubbs + + renamed stopped to stop_requested + + This is more descriptive of what the variable actually does. It signals + the callback to stop the audio. + +commit 8f3e8f196711d729de6c2dc1ed1ef2d086f99955 +Author: William Hubbs +Commit: William Hubbs + + moved the audio_mutex code to alsa + + This is not needed for native sound support, so it has been moved into + the alsa specific code. + +commit e49acbb59acdbad827da2fc4dd7061e7fe2de35a +Author: William Hubbs +Commit: William Hubbs + + removed a debug print + +commit 24bcdf5666d2546b9177b54b25d2fbfc54ab804b +Author: William Hubbs +Commit: William Hubbs + + another termination fix + + espeak_thread needs to signal softsynth_thread once more as it is going + town so that softsynth_thread will see that should_run is now 0 and + terminate. + +commit 5ec3809c599981f79db87f41f4b181eb5456a4f7 +Author: William Hubbs +Commit: William Hubbs + + wake up espeak_thread when softsynth_thread terminates + + espeak_thread needs a signal since it might be sleeping and + should_run has changed. This makes sure it terminates. + +commit 5ebe506026cf2a5953ba9773d2e2c434e8bbc6f4 +Author: William Hubbs +Commit: William Hubbs + + more mutex fixes + + Make sure that should_run is protected by the mutex in the softsynth + thread. + +commit d5fd5d69b84cdcde67357a5a934b343e46a32cb2 +Author: Chris Brannon +Commit: William Hubbs + + don't wait on a condition variable if should_run is false + +commit 633743117c7067bb7f7a7a12f2edbe6bb463a366 +Author: William Hubbs +Commit: William Hubbs + + mutex fixes + + We need to make sure that should_run is protected by the mutex. + +commit 1750b92cfb0e5d5a39564ea8d949113c4e0c3409 +Author: William Hubbs +Commit: William Hubbs + + fixed signal handling issue + + The signal handler stopped working after I moved the initialization + calls to the main function. Creating the signal handler thread first + fixed this issue. + +commit eb74a3ce171515dd1f2970dfb3d1b6c2f07c6d79 +Author: William Hubbs +Commit: William Hubbs + + removed an unnecessary call to espeak_Terminate() + +commit dd00775695f713667b2fc295feab6a2a2fe1926e +Author: William Hubbs +Commit: William Hubbs + + initialization update + + The main function now initializes espeak and opens the softsynth before + starting the threads. This insures that the resources we need are + active. + +commit 6a15f2cccf4d98e112f09ae64e68773c028b76f6 +Author: William Hubbs +Commit: William Hubbs + + fixed first wait in softsynth thread + + The thread should wait if there is nothing in the queue and if there is + not a request to stop. + Thanks to Chris Brannon for the patch. + +commit 3687f16b09d7ff37f73ca0f98acd8dedd4ce18c1 +Author: William Hubbs +Commit: William Hubbs + + wait for acknowledgements correctly + + pthread_cond_wait() can have spurious wakeups, so we need to be sure + that the condition is actually true when we return from this function. + Thanks to Chris Brannon for the patch. + +commit 938e10b66a14237cdff734ae5b97525f9c4ae9cc +Author: William Hubbs +Commit: William Hubbs + + removed a nested lock/unlock + +commit 975765289b3348219d0db8b2d64e2f4f7747f9f2 +Author: William Hubbs +Commit: William Hubbs + + made sure all cond_wait and cond_signal calls are inside lock/unlock + calls + +commit b8c7247feb05a07bab653cab2a6be50a4a17fd5d +Author: William Hubbs +Commit: William Hubbs + + removed acknowledge_guard and substituted queue_guard + +commit 1091182f884cb8187ce3cdaf3723243deaa4dcb2 +Author: William Hubbs +Commit: William Hubbs + + removed a debug print call + +commit 0bf2cae5a6cd35ea7ee78fbb136ccb58f6937b3e +Author: William Hubbs +Commit: William Hubbs + + moved lock/unlock in queue_process_entry + + The only time queue_process_entry should lock the queue gard is when it + is removing the item from the queue. This happens only when the item + was successfully processed. + +commit 554a03d26c147958b99b78690214e195cda65c41 +Author: William Hubbs +Commit: William Hubbs + + white space fix + +commit b7f324072f26fa31a8d9772f38bdf1f920504223 +Author: Christopher Brannon +Commit: William Hubbs + + Fix concurrency bugs. + + 1. Don't lock or unlock queue_guard during queue_clear. + It is locked when queue_clear is called, and it should remain so. + 2. Protect runner_must_stop with queue_guard in + the request_espeak_stop function. + The following condition should always hold: queue_guard is locked while + testing or modifying runner_must_stop. + 3. Rename stop_guard to acknowledge_guard. This is a more + descriptive name. This mutex simply protects the acknowledgement of + the stop request from being lost. + 4. Remove the pthread_mutex_lock from the top of queue_process_entry, + because queue_guard is already locked when the function is called. + +commit a8cad20de898002465fad6f3cf42f381f2a33812 +Author: William Hubbs +Commit: William Hubbs + + more multithreading work + + Rearranged the queue handling code so that queue.c is generic. Also + rearranged several functions in the threads. + +commit 42c3f76a083890c49fcb7d92a2f695f69e4882b4 +Author: William Hubbs +Commit: William Hubbs + + moved include for pthread.h to espeakup.h + +commit 3e8e7d12ae89b4b2c00596cf88fcb35fd4b5b20e +Author: William Hubbs +Commit: William Hubbs + + added back the declaration for softFD + +commit af5717b8cb3d9c2232f20f90d32601c0f7021fca +Author: William Hubbs +Commit: William Hubbs + + moved queue_add_xxx functions to softsynth thread + +commit c6b57885c9479f4d85831b2082206bef685cd74d +Author: William Hubbs +Commit: William Hubbs + + removed declaration of rate from main + +commit d82bfcd09ccd4145d17473bc9ae60af223a5f66e +Author: Christopher Brannon +Commit: William Hubbs + + Make one thread responsible for handling espeak interaction. + + Most of the idea for this change came from William: + Renamed queue_runner to espeak_thread. Moved espeak initialization + and termination to espeak_thread. The while loops that process + the queue now use the variable should_run. + +commit 0fdca827b851fd0beb9f476c52ec5568ed36174e +Author: William Hubbs +Commit: William Hubbs + + check for terminalFD after select() + + If terminalFD has something to read, we break out of the loop in the + softsynth thread. + +commit 474580b08b32d713ffb6f23c486685f1927e12c0 +Author: William Hubbs +Commit: William Hubbs + + add pipe to wake up the softsynth thread + + This adds a pipe to wake up the softsynth thread, in case we receive a + signal while it is in a select. Thanks to Chris Brannon. + +commit c5fce64f259bce473cd3c9371d7b095639a87fe5 +Author: William Hubbs +Commit: William Hubbs + + removed open_softsynth and close_softsynth + + The thread can now handle the softsynth device, so main doesn't need to + call these functions. + +commit a58f93cd74fead43927093d36fc775a976788a4b +Author: William Hubbs +Commit: William Hubbs + + renamed reader_thread to softsynth_thread + +commit dfc9bbff6518b2de6e4464fd348ae460766606fb +Author: William Hubbs +Commit: William Hubbs + + fixed should_run declaration + + Removed the local declaration of should_run and set up the extern. + +commit 9d1cabdd0d513c45bafdf7cc9c62b503f4a0f31d +Author: William Hubbs +Commit: William Hubbs + + started work on multi-threading more of the program + + The goal is to create threads for the reader, que runner/espeak + processing and signal handling. + As of this commit, this code is still being worked on, so it is broken. + +commit f58d9984ce6d615158d53a6cf1b5d503296973ab +Author: William Hubbs +Commit: William Hubbs + + Now the queue runner/softsynth handler clears the queue + + Thanks to Chris Brannon for the patch. + +commit 24e7d667bce7568585e1e644b1935c8fe0709b75 +Author: William Hubbs +Commit: William Hubbs + + queue fixes + + This adds retry processing back to the queue functions. queue_remove + should only be called after the head entry on the queue is processed + successfully. + +commit 26ab109bd8e14fd3d26a434cac2e5760b23dbf0a +Author: William Hubbs +Commit: William Hubbs + + moved the check for stop out of the loop + + In the callback, we should check to see if the stopped flag is true + whether or not we are processing audio. + +commit b108764b02e0d6eb1e8a3074cf2f85f10eb01d03 +Author: William Hubbs +Commit: William Hubbs + + removed the audio_callback variable + +commit 739d79cff89f2792aa47813e08bdcbb3065c32de +Author: Christopher Brannon +Commit: William Hubbs + + Select audio mode before initializing espeak. + +commit ec9d8b1ee23095afadd07bd05cbf1ca21df11b8f +Author: Christopher Brannon +Commit: William Hubbs + + Add error-checking to the snd_pcm_set_* calls. + + These can fail. They do more than simply manipulate a structure. + +commit a5d1a48f42bbb3de67551113c1f15da10f7b916d +Author: Christopher Brannon +Commit: William Hubbs + + Obtain sample rate from the value of espeak_Initialize. + + espeak uses a sample rate of 22050 HZ, but let's not rely on that knowledge. + espeak_Initialize returns the sample rate on success, + so rely on that value when selecting a rate. + +commit 3bb78df86c3a135660864e1e07c1d5266a575bce +Author: William Hubbs +Commit: William Hubbs + + Do not set the period. + +commit 94e23a3a027dfd887f6713e745a0b97ec09dfbc7 +Author: William Hubbs +Commit: William Hubbs + + fixed error condition check in alsa.c + + The check was looking for a specific error when it should have been just + checking for failure. + +commit a69342fcada7fe6533b81c1ae0bad23f983a399a +Author: William Hubbs +Commit: William Hubbs + + removed some blank lines and put the variables at the top of the file + +commit 91b8960b6add66a982327e68d51f75d25f828af8 +Author: Christopher Brannon +Commit: William Hubbs + + Protect the stopped variable with a mutex. + + An oversight. Should have done this in the initial commit. + volatile does not imply atomic. + +commit 0ad70b4eaa35d57867f20c631f60841fde824e20 +Author: William Hubbs +Commit: William Hubbs + + Revert "fixed stop_speech issue" + + This reverts commit 1c440e5a42ef2606c0330f816b00172ab309505c. + +commit 1d02169aa584ebb8c8739c4b1255abd3ee51e709 +Author: William Hubbs +Commit: William Hubbs + + alsa support is conditional + + This commit updates the makefile and the documentation to explain how to + build alsa support. It has not been fully tested, so it is not built by + default. Also, I was able to remove the conditional compile directives + from the source. + +commit 1c440e5a42ef2606c0330f816b00172ab309505c +Author: William Hubbs +Commit: William Hubbs + + fixed stop_speech issue + + The stop_speech function needs to test the return code from + espeak_Cancel() to be sure the operation was successful before + signaling the callback to stop the audio. + +commit 08e46c58a804c380f73a8be3403663af790a48bd +Author: William Hubbs +Commit: William Hubbs + + indentation fixes + +commit d373fb2aa7fbf673594cd98225877c6998dc99ad +Author: Christopher Brannon +Commit: William Hubbs + + An initial stab at ALSA support. + + It's very raw right now. + +commit b31985f97c30b043dba7b77c5af0b42d3a65fcdd +Author: William Hubbs +Commit: William Hubbs + + released v0.71 + +commit d7dd0f919dc82cc0e497700412980ce771a5d7df +Author: William Hubbs +Commit: William Hubbs + + fixed initialization issues + + We were not returning exit codes properly if we were unable to open the + softsynth or if the daemon was already running. + +commit 2db53856a90a82c99c759399a1dfa5e704ce4f4a +Author: William Hubbs +Commit: William Hubbs + + fixed typo in tarball script + +commit 55f8ebf98a0fd2caef675e22499798b8ead99b12 +Author: William Hubbs +Commit: William Hubbs + + released v0.70 + +commit 69f1e8554a65b3eb0bdfcaf56bbcea86acc7e926 +Author: William Hubbs +Commit: William Hubbs + + The tarball script now adds a ChangeLog + +commit 0e47c95015a8d0ca3c777717f3187bafc615f201 +Author: William Hubbs +Commit: William Hubbs + + updated README + +commit c235a3b063a524cd308f2512c14502b5dee71434 +Author: William Hubbs +Commit: William Hubbs + + added .indent.pro to the repository + +commit d7c81f5117442d66358efb52232d51f45a90d4e8 +Author: William Hubbs +Commit: William Hubbs + + indentation fixes + +commit 3ddbb94e37a5183a0010a2e1ae46f4a64d39bba4 +Author: Christopher Brannon +Commit: William Hubbs + + multithreading + + Make espeakup a multi-threaded program. One thread reads from the softsynth + device, queuing text and synthesis commands. The other thread processes + items from the queue. + +commit 3a8323f98c702443f65b35bbfa84d3ae2c4c9b39 +Author: William Hubbs +Commit: William Hubbs + + Fixed typo in README + +commit e7d300a183668d24cc1250083bd09ab1abcc4cfb +Author: William Hubbs +Commit: William Hubbs + + turn off espeak's default processing of uppercase letters + + This needs to be turned off since speakup processes upper case by + raising the pitch. + +commit a1510b5e93de11dbf70fec2295b30a87656b4824 +Author: William Hubbs +Commit: William Hubbs + + indentation fixes + +commit 3dbdcb21cbb28dc6cebd80077a6e774cc2673bb6 +Author: William Hubbs +Commit: William Hubbs + + Aespeakup should not drop all non-ascii characters. + + This fixes an issue with non-english languages. + Thanks to Samuel Thibault for the patch. + +commit 9551ba81d9bffad667f0d5f864d07c767e2e70e6 +Author: William Hubbs +Commit: William Hubbs + + espeakup 0.60 + +commit 6366b41bdf7b28b392de8ca0c2a246a8360f9293 +Author: William Hubbs +Commit: William Hubbs + + espeakup v0.6 + +commit 40f152e11fb4a89546e459861ac0348c58c8d449 +Author: William Hubbs +Commit: William Hubbs + + allow users to override CFLAGS + + This fixes an issue with the Makefile that was not allowing users to + override cflags and keeping -Wall in the flags when compiling. + +commit 4e7ae23757290ef299a3ba4285bc031de425d788 +Author: William Hubbs +Commit: William Hubbs + + created tarball script + + This commit adds a script to create a tarball from the repository and + removes this functionality from the makefile. + +commit 9ee3fd433cb2513462327fd815f108dc9abc8e8e +Author: William Hubbs +Commit: William Hubbs + + documented --default-voice in man page + + This commit adds the documentation for --default-voice to the espeakup + man page. + +commit e2493db48e69307eeee3390d9329212cb6403613 +Author: William Hubbs +Commit: William Hubbs + + add --default-voice option to the help and README + + This commit adds the documentation to the help and README files for the + --default-voice command line option. + +commit 2351b5d489454c32c4a5c2ccdb1da609ded03b70 +Author: William Hubbs +Commit: William Hubbs + + add support for setting the default voice + + This adds support for a --default-voice or -V (upper case) command line + option which will set the default voice espeakup uses. This takes a + name of an espeak voice -- for example: + + espeakup --default-voice=en-us + + or + + espeakup -V en-us + +commit da15136aa7b8c12024d9178d1ba6b29037984a75 +Author: William Hubbs +Commit: William Hubbs + + only one espeakup daemon should be running + + This fixes a bug which would allow espeakup in debug mode to be run even + if espeakup was already running as a daemon. + +commit 8dca597f29e0ef54525f5f717a7058a037d2e9fc +Author: William Hubbs +Commit: William Hubbs + + Added a version script + + I added a version script. This is used in the Makefile to get the + version of espeakup when none is specified when a tarball is created. + +commit bbf77d918dac93e1bec7fc90c0b8b34dfb5a8e65 +Author: William Hubbs +Commit: William Hubbs + + Cleaned up warnings and adjusted CFLAGS + + This commit cleans up warnings and adjusts CFLAGS. Thanks to + samuel.thibault@ens-lyon.org. + +commit 7db55303088588a19fcde1c804268c984f6008d8 +Author: William Hubbs +Commit: William Hubbs + + Espeakup version 0.51. + +commit 341fa7ba425892c12ae293584aacd9028d520e62 +Author: William Hubbs +Commit: William Hubbs + + fixed install command in makefile. + +commit 0f24afef95c2bdda474d77bc774f19003015da46 +Author: William Hubbs +Commit: William Hubbs + + espeakup v0.5 + +commit c12ec3e1b060b6e3ec1ac53db33b6f87877e9109 +Author: William Hubbs +Commit: William Hubbs + + moved version definition + + This commit moves the version definition to espeakup.c instead of cli.c + +commit a8876a79644f36453a7edaef4c0860c7d2402c9b +Author: William Hubbs +Commit: William Hubbs + + fixed the license in the man page + + The man page said that espeakup is under gpl version 2 or later, but it + is under version 3 or later, so I fixed the man page. + +commit 2b96dd2a026bb2220071699fc51cdf11b9412d82 +Author: William Hubbs +Commit: William Hubbs + + updated man page + + This commit re-words the description of espeakup in the man page. + +commit 17553c3c391e011a1ccf90179c634003d2a61519 +Author: William Hubbs +Commit: William Hubbs + + fixed the makefile + + This commit removes the definitions for CC, RM and INSTALL from the + makefile so that it will use system defaults for these commands. + +commit ace8acf7d01cc256c1df96d3b03e21806772edb5 +Author: William Hubbs +Commit: William Hubbs + + fixed hyphenation + + This commit turns off hypenation in the man page. + +commit 84c473b690633999f47478dbf00c766d1a31628b +Author: William Hubbs +Commit: William Hubbs + + added man page + + This commit adds a man page for espeakup. + Thanks to Chris Brannon for writing it. + +commit f7ddd8dc77927d21a07479f80969df031af396f2 +Author: William Hubbs +Commit: William Hubbs + + Released v0.4. + +commit a3901a7e4c0d273f2ad5352f939714fe235166e4 +Author: William Hubbs +Commit: William Hubbs + + fixed a bug in process_command + + One of the switch statements in process_command did not have a default + label, which lead to undefined behavior. + Thanks to Chris Brannon for the patch. + +commit 36b05aec419a7ab7bc3b66358f62122096ec9ce2 +Author: William Hubbs +Commit: William Hubbs + + Added support for the punctuation command from speakup + +commit c48b05d7437435c0c7513e9d98ab04b565c87f92 +Author: William Hubbs +Commit: William Hubbs + + moved all variable definitions to the top of the Makefile. + +commit 82fa63600b9377fa590a2c97ed737fd8c85a622c +Author: William Hubbs +Commit: William Hubbs + + fixed the makefile + + Added espeakup.h as a dependency in the makefile so that the sources + will be compiled if it changes. + +commit d7e8dc2b342b5a810ec561535ca0426969f519ea +Author: William Hubbs +Commit: William Hubbs + + Revert "fixed the length calculation when a flush is processed." + + This reverts commit 66cb5a7b5cfe0e569525935d03b0843ee85a8afc. + +commit 66cb5a7b5cfe0e569525935d03b0843ee85a8afc +Author: William Hubbs +Commit: William Hubbs + + fixed the length calculation when a flush is processed. + +commit 62deb008bc658d925bd86fb4172b12779b9cad18 +Author: William Hubbs +Commit: William Hubbs + + fixed the number of bytes to move in the memmove() call + +commit 14858818d3cf38886aef5089982522feb9a8edfb +Author: William Hubbs +Commit: William Hubbs + + changed strcpy to memmove + + The areas pointed to by strcpy() cannot overlap, so we need to use + memmove() in case that happens. + Thanks to Chris Brannon for pointing this out. + +commit 6bec55ca5789e26ee315e890f4937c1451b8cd07 +Author: William Hubbs +Commit: William Hubbs + + changed process_buffer to use the isprint() call. + +commit 1b608481a4062f3a8f98192e50acfcb73cf577e2 +Author: William Hubbs +Commit: William Hubbs + + the main loop now uses strrchr and strcpy + + The idea for this change came from another patch submitted by Chris + Brannon. We now use strrchr to look for the flush character and strcpy + to move the remainder of the buffer to the beginning. + +commit faab1893893fa0c97263a0edf965cf4f67bd1294 +Author: William Hubbs +Commit: William Hubbs + + Fixed the select call + + The select call was moved to be in the if statement below it since the + return code is not needed after that statement is processed. + +commit 24607b1cc8000d4d95128e96662240dbce385358 +Author: William Hubbs +Commit: William Hubbs + + made the synth flush character a constant for readability + +commit c8e2a35763624463d1006a83ab0125603813d239 +Author: William Hubbs +Commit: William Hubbs + + fixed an off-by-one error + + The loop can start at length-1 since we know that the last character in + the buffer is a null. + Thanks again to Chris Brannon for finding this. + +commit f76d00f6afefb8de92bf205d16d84f488b91615d +Author: William Hubbs +Commit: William Hubbs + + removed the callback function + + This commit removes the synthcallback function since it wasn't doing + anything. Also, it has been reported that this may be causing the + sluggishness when espeakup is asked to shut up. + Thanks to Chris Brannon for finding this. + +commit 17f07e8cd175520c8fe16880f9f578e0f49579fc +Author: William Hubbs +Commit: William Hubbs + + released v0.3. + +commit 9b0c6a8224980c8637302d9e680cccef4ed0043d +Author: William Hubbs +Commit: William Hubbs + + fixed the volume multiplier + + The volume range is actually 0-200 instead of 0-100, so the multiplier + needed to be adjusted. + +commit c7e3835fbd2ab4d9ae5162488163d22c8bd9c811 +Author: William Hubbs +Commit: William Hubbs + + Updated ToDo list + +commit 527fb136de9d01c752f6f6d03d2ac42b89a94499 +Author: William Hubbs +Commit: William Hubbs + + starting work toward supporting changing voices + + This commit adds a set_voice() function which will ultimately allow the + user to switch voices. + +commit f52c03ec2be8cc67e680eda0cdb6bbb051b858cd +Author: William Hubbs +Commit: William Hubbs + + Fixed a typo. + +commit 8d3552c9642aec00f5ecc89dbbccd181244d9bfa +Author: William Hubbs +Commit: William Hubbs + + updated readme + +commit 1f784be8911bd2917e697630de3da05da2814ab4 +Author: William Hubbs +Commit: William Hubbs + + added support for long command line options + +commit 037019de3a74c191349bebc03289a11ab7cead42 +Author: William Hubbs +Commit: William Hubbs + + Espeakup v0.2 + +commit 943ff9d3dc50184a359ee7b39d57b4baaba0657c +Author: William Hubbs +Commit: William Hubbs + + updated README + +commit 5ddeb1e978bc637b4db22f19d0db8e448599f5e0 +Author: William Hubbs +Commit: William Hubbs + + indentation fixes + +commit ccc9c4aa4ed3f16d3781b92fbd6d6ec013627c5c +Author: William Hubbs +Commit: William Hubbs + + modified rate offset + + This commit moves the rate offset to 84 instead of 80 so that the + highest espeak rate can be reached by setting the speakup rate to + the maximum. + +commit 96a3b198508172e30bb0614563db94f83e45ce03 +Author: William Hubbs +Commit: William Hubbs + + fix flush processing + + This removes flush processing from process_command() and fixes + the code in the main loop so that it does not ignore the 0 position + in the buffer. + +commit 5bc67dc49d61468968b25cda1340091fced573a0 +Author: William Hubbs +Commit: William Hubbs + + updated ToDo list. + +commit 02e72bda39b4c26bcc1a67d701a405427e3a6f8a +Author: William Hubbs +Commit: William Hubbs + + adjusted the rate multiplier + + This gets us closer to espeak's top speed, which is 390 wpm. + +commit ebcbcac9d2b230a37347f60aa3e2715a07bb13a6 +Author: William Hubbs +Commit: William Hubbs + + removed an extra assignment statement + +commit d2d763b36ba477c18a04933ee49b68f71dd641a2 +Author: William Hubbs +Commit: William Hubbs + + moved flush processing into main loop + + This patch from Kirk Reiser attempts to increase + responsiveness by moving the flush processing into the main loop. + +commit 564db7981e1aeda4eb84958d1f66c6474803991f +Author: William Hubbs +Commit: William Hubbs + + put back the select code + + This needed to be put back to keep espeakup from using 100% of the cpu. + +commit 5005b9ddde90aeab3948f9123491463d0e319528 +Author: William Hubbs +Commit: William Hubbs + + removed code that uses select + + I was using the wrong type for the return value for read(). + +commit 3e7e5be2b78bdc1dbaa400d3b8e35ac66eab3cbd +Author: William Hubbs +Commit: William Hubbs + + fixed bug with volume setting + + Now the volume setting should be announced again. + +commit f973c9ec3fa92560279acede8386beeaa5f6835b +Author: William Hubbs +Commit: William Hubbs + + cleaned up prototypes + + This commit gets rid of extra spaces in some function prototypes. + +commit 498ce65db7d789b9639b96240555e48ab3a910b6 +Author: William Hubbs +Commit: William Hubbs + + cleaned up process_command + +commit aac77a3cf1edd6b503bcaada06a575ac06efa6f7 +Author: William Hubbs +Commit: William Hubbs + + ignore object files + +commit de8d4d9dc3bb7afd51eef89c0c7c2fb6d630b7a7 +Author: William Hubbs +Commit: William Hubbs + + fixed an include for gcc 4.3 + +commit b34e397717bae998bd2280a0774a04cd37ea1791 +Author: William Hubbs +Commit: William Hubbs + + clear the queue when we catch a signal + +commit 4c30dac5e16c84d92f12aa06c3cf5279c726d8db +Author: William Hubbs +Commit: William Hubbs + + added prototypes for queue functions + +commit 2bf3b17ffcbb3705afc23957e77fba2dc7abbda9 +Author: William Hubbs +Commit: William Hubbs + + removed debug flag from cflags + +commit 655894ee2a240036e966a5854fc71bb788aebe25 +Author: William Hubbs +Commit: William Hubbs + + added queueing support + + I have added queueing support so that when we read from the softsynth we + can put the text and commands we have read into a queue. This will + allow us to retry calling espeak_synth() if we fill espeak's internal + buffer. + +commit 86e93edeb09774d3689cca7f9fe96aa484f3bd6d +Author: William Hubbs +Commit: William Hubbs + + removed softsynth code from main module + +commit 261c6db032a0c4654c0b77055701223bee055dcb +Author: William Hubbs +Commit: William Hubbs + + Added ToDo list + +commit 029dd03251d24dc5c0a1b0e5a16706c0ca73180d +Author: William Hubbs +Commit: William Hubbs + + modularize the code + + This commit just re-arranges the source so that it is easier to work with. + +commit 882e9c20a547707c2d63a70414de951c50e5d4db +Author: William Hubbs +Commit: William Hubbs + + clean up the main function + + This commit cleans up the main function and moves command line processing + to a separate function. + +commit 4d2f76d6e111bb45cdf336f4be8140bcab3d51b6 +Author: William Hubbs +Commit: William Hubbs + + removed makedist + + The functionality to create a tarball has been moved into the makefile. + Now it is possible to create a tarball by doing: + make tarball - creates a tarball of the llast tagged version. + make TAG=gittag tarball creates a tarball based on the tag that is given to it. + +commit 1802877912be8e4b68541ed07d738841947463fd +Author: William Hubbs +Commit: William Hubbs + + Removed init scripts. + + It will be best to let packagers write init scripts for their distributions, + so I am removing them from this repository. + +commit 3d83e0f6d152035890d7dbecb5961ee79234d476 +Author: William Hubbs +Commit: William Hubbs + + updated readme + + I added an acknowledgements section. + +commit b76fada0b61873bb5228246e2585fea3ca690aba +Author: William Hubbs +Commit: William Hubbs + + fixed makefile + + The reference to $(PROGRAM) should have been $<. + This is fixed. + +commit c2c1d429db31693a60b8e93479a4d4fe5d31588a +Author: William Hubbs +Commit: William Hubbs + + added redhat init script, thanks to William Acker. + +commit c7bece776d13a1c5ac1a52967ffb5cd1b3ed9a9c +Author: William Hubbs +Commit: William Hubbs + + fixed makefile + + There was a bug in the makefile which was not installing the binary correctly. + This is now fixed. + +commit 22ea5c4d1d5db2d4d24e5a89437fac0d6940edf7 +Author: William Hubbs +Commit: William Hubbs + + updated makedist + + The makedist script now excludes itself and .gitignore when creating a tarball. + +commit 9402716c32c124fff4614b1555f7219f0bbe7135 +Author: William Hubbs +Commit: William Hubbs + + cleaned up command line option processing + +commit 05b115abbb8aa1d14b0f1c38c1212918fc9d8c24 +Author: William Hubbs +Commit: William Hubbs + + fixed typos in makedist script. + +commit 16beed096923abea8a7768d1ee6224419faabd0b +Author: William Hubbs +Commit: William Hubbs + + added a script to make tarball releases. + +commit 6ecc3182dab397d7b197e18d7bf78ca8c1316f71 +Author: William Hubbs +Commit: William Hubbs + + added a version command line option and variable. + +commit 96871c66201b77fddf5b80106b8f136fe825df87 +Author: William Hubbs +Commit: William Hubbs + + added destdir and prefix to the makefile for packaging. + +commit c7e0e28ad1102c395958c3baab70b4a8d20203bc +Author: William Hubbs +Commit: William Hubbs + + added gpl + +commit 02c88e949a9e44e16fa7ad6c289f3c476e0becb2 +Author: William Hubbs +Commit: William Hubbs + + adjusted multipliers + + I adjusted the pitch and volume multipliers. + This should allow us to come closer to the maximum espeak settings. + +commit d7de943a3a1b748e2cb27f42af483339de8aa444 +Author: William Hubbs +Commit: William Hubbs + + added frequency support + + This patch, also from Kirk Reiser, adds frequency support. + +commit cddead8aa951e0ad68ba241456a8e5f36c6fb2f5 +Author: William Hubbs +Commit: William Hubbs + + pid file support + + This commit adds support for a pid file so that we can be stopped and + started by init systems. + +commit b51cf9d774cc5a2abd13480238b951e20680ec24 +Author: William Hubbs +Commit: William Hubbs + + Added a signal handler + + This commit adds a signal handler so that espeakup will terminate cleanly. + +commit 61aac5ecb58ac49fc9060d19dde2dbda996e8e9f +Author: William Hubbs +Commit: William Hubbs + + moved some variables + + This commit removes the softsynth file descriptor and the debug flag + from the synth structure. These will need to be accessed from a signal + handler and there is no way to pass the structure to it. + Also, the process_data function now works with local variables and assigns + them to the synth structure, avoiding allocating a buffer with malloc/free. + +commit eb5cb3d36d35887907e13aeee0cad8fcc1b73baa +Author: William Hubbs +Commit: William Hubbs + + fixed volume + + I applied another patch from Kirk Reiser which fixes the volume setting. + Thanks to Kirk for the patch. + +commit 7604cac68c53dd3c01cfc0e131e2a7f985b40ff7 +Author: William Hubbs +Commit: William Hubbs + + fixed the garbage characters bug + + This fixes the bug that was causing garbage characters to be spoken. Also + it sets the initial voice to "default". + +commit b745e0c48b614143fb4df04ba878af29f4ece587 +Author: William Hubbs +Commit: William Hubbs + + more error checking + + I moved the read call out of process_data and into the main loop. + Also, error checking was added for select() and read(). + +commit c3b0e8d0da9efdf9e719ba3fbe599640a5db7dce +Author: William Hubbs +Commit: William Hubbs + + code cleanup + + This patch adds the length of the buffer to the synth structure and + clears the buffer before we use it. + Thanks to Kirk Reiser for the patch. + +commit c4839ac78b967b4677531afe7568156c907e6bda +Author: William Hubbs +Commit: William Hubbs + + added maxBufferSize constant + +commit 754358f1731e58990b4c4131d4b900a5d2a5049a +Author: William Hubbs +Commit: William Hubbs + + added cli option support + + This commit adds support for command line options and also adds a debug option. + +commit 572f33337811973091f44e54e6b4fcb13ae689d9 +Author: William Hubbs +Commit: William Hubbs + + added volume support + + I added support for setting the volume. + +commit 4e3bbdb0b02eb1f12c087909e6437a31a9c60d7b +Author: William Hubbs +Commit: William Hubbs + + initial import diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ad67b61 --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +PREFIX = /usr/local +BINDIR = ${PREFIX}/bin +MANDIR = ${PREFIX}/share/man + +DEPFLAGS = -MMD +WARNFLAGS = -Wall +CFLAGS += ${DEPFLAGS} ${WARNFLAGS} + +LDLIBS = -lespeak -lpthread + +INSTALL = install +BINMODE = 0755 +MANMODE = 0644 +CHANGELOG_LIMIT?= --after="1 year ago" + +SRCS = cli.c \ + espeak.c \ + espeakup.c \ + queue.c \ + signal.c \ + softsynth.c \ + stringhandling.c + +OBJS = ${SRCS:.c=.o} + +all: espeakup + +changelog: + git log ${CHANGELOG_LIMIT} --format=full > ChangeLog + +install: espeakup + ${INSTALL} -d ${DESTDIR}${BINDIR} + ${INSTALL} -m ${BINMODE} $< ${DESTDIR}${BINDIR} + ${INSTALL} -d ${DESTDIR}${MANDIR}/man8 + ${INSTALL} -m ${MANMODE} espeakup.8 ${DESTDIR}${MANDIR}/man8 + +espeakup: ${OBJS} + +clean: + ${RM} *.d *.o + +distclean: clean + ${RM} espeakup + +-include ${SRCS:.c=.d} diff --git a/README b/README new file mode 100644 index 0000000..b8ed359 --- /dev/null +++ b/README @@ -0,0 +1,70 @@ +espeakup connector +======================= + +espeakup is a program which makes it possible for speakup to use +the espeak software synthesizer. It does this by reading speakup's +softsynth device and passing the text to espeak which actually speaks. + +Requirements +============ + +This program works with the speakup screen reader, which can be obtained +from http://linux-speakup.org, and the espeak software speech +synthesizer which can be obtained from http://espeak.sourceforge.net. +You must have both of these installed and operational. Setting them up +is beyond the scope of this document. + +Installation +============ + +The preferred way to install espeakup is using your distribution's +packaging system, but if your distribution does not have a package for +espeakup yet, espeakup just uses a Makefile, so you should be able to +change to the source directory, then type make, then as root, make +install. + +Starting Up +=========== + +This program should be run after speakup is set up to communicate with a +software synthesizer and after /dev/softsynth exists. The way this is +done is distribution specific, so it is beyond the scope of this +documentation. + +Command Line Options +==================== + +Espeakup currently accepts the following command line options: + + --default-voice=voice, -V voice Set default voice. + --debug, -d Debug mode (stay in the foreground). + --help, -h Show this help. + --version, -v Display the software version. + +Getting the Latest Version +========================== + +It is possible to download a tarball from github of any released version +as follows: + +wget http://www.github.com/williamh/espeakup/tarball/vx.y + +If you need a tarball for packaging purposes, one is available from +ftp://ftp.linux-speakup.org/pub/linux/goodies/espeakup-x.y.tar.bz2. + +The url for the git repository is git://github.com/williamh/espeakup.git. + +Acknowledgements +================ + +I would like to thank Marc Mulcahy, the author of the speakup to +TTSynth connector, on which this work is based. Also, I would like +to thank Kirk Reiser and Jonathan Duddington, the +authors of Speakup and Espeak, respectively, for their work. + +Questions +========= + +You can contact me with questions, bugs, patches, etc, at +w.d.hubbs@gmail.com or on the speakup mailing list. I hope you find +this software to be useful. diff --git a/README.md b/README.md deleted file mode 100644 index e1395b0..0000000 --- a/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# espeakup connector - -espeakup is a program which makes it possible for speakup to use -the espeak-ng software synthesizer. It does this by reading speakup's -softsynth device and passing the text to espeak-ng which actually speaks. - -## Requirements - -This program works with the speakup screen reader, which can be obtained -from http://linux-speakup.org, and the -[espeak-ng](https://github.com/espeak-ng/espeak-ng) software speech -synthesizer. - -You must have both of these installed and operational. Setting them up -is beyond the scope of this document. - -## Installation - -The preferred way to install espeakup is using your distribution's -packaging system, but if your distribution does not have a package for -espeakup yet, espeakup just uses meson, so you should be able to -change to the source directory, then type: - -```bash -meson setup . ./build -cd ./build -ninja -sudo ninja install -``` - -## Starting Up - -This program should be run after speakup is set up to communicate with a -software synthesizer and after /dev/softsynth exists. The way this is -done is distribution specific, so it is beyond the scope of this -documentation. - -## Acknowledgements - -I would like to thank Marc Mulcahy, the author of the speakup to -TTSynth connector, on which this work is based. Also, I would like -to thank Kirk Reiser and Jonathan Duddington, the -authors of Speakup and Espeak, respectively, for their work. - -## Filing Bugs - -Bugs should be filed on our bug tracker at -https://github.com/linux-speakup/issues. diff --git a/TODO b/TODO new file mode 100644 index 0000000..ec1d210 --- /dev/null +++ b/TODO @@ -0,0 +1,11 @@ +This file contains a list of improvements that need to be made to +espeakup. + +Voice and language support should be added at some point. +This will consist of the following: +- add a function which will allow switching voices. (completed on 9/27) +- add a function/command which will allow speakup to find out which + voices espeak supports. +- define and add the command to speakup which will allow it to switch + voices. + diff --git a/src/cli.c b/cli.c similarity index 86% rename from src/cli.c rename to cli.c index 8453587..31db4b0 100644 --- a/src/cli.c +++ b/cli.c @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2008 William Hubbs * @@ -23,8 +23,6 @@ #include #include "espeakup.h" -#include "stringhandling.h" -#include "version.h" /* pid path */ extern char *pidPath; @@ -32,20 +30,17 @@ extern char *pidPath; /* default voice */ extern char *defaultVoice; -/* Whether to drive ALSA volume */ -extern int alsaVolume; - /* command line options */ const char *shortOptions = "P:V:adhv"; const struct option longOptions[] = { {"pid-path", required_argument, NULL, 'P'}, {"default-voice", required_argument, NULL, 'V'}, - {"alsa-volume", no_argument, &alsaVolume, 1}, {"acsint", no_argument, NULL, 'a'}, {"debug", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, - {0, 0, 0, 0}}; + {0, 0, 0, 0} +}; static void show_help() { @@ -53,7 +48,6 @@ static void show_help() printf("Options are as follows:\n"); printf(" --pid-path=path, -P path\t\tSet path for pid file.\n"); printf(" --default-voice=voice, -V voice\tSet default voice.\n"); - printf(" --alsa-volume\t\t\t\tDrive the ALSA volume.\n"); printf(" --debug, -d\t\t\t\tDebug mode (stay in the foreground).\n"); printf(" --help, -h\t\t\t\tShow this help.\n"); printf(" --version, -v\t\t\t\tDisplay the software version.\n"); @@ -73,15 +67,18 @@ static void show_version(void) void process_cli(int argc, char **argv) { int opt; + char *cp; do { opt = getopt_long(argc, argv, shortOptions, longOptions, NULL); switch (opt) { - case 'P': - pidPath = dupeString(optarg); + case 'p': + cp = strdup(optarg); + if (cp != NULL) + pidPath = cp; break; case 'V': - defaultVoice = dupeString(optarg); + defaultVoice = strdup(optarg); break; case 'a': espeakup_mode = ESPEAKUP_MODE_ACSINT; @@ -96,7 +93,6 @@ void process_cli(int argc, char **argv) show_version(); break; case -1: - case 0: break; default: show_help(); diff --git a/doc/espeakup.8.ronn b/doc/espeakup.8.ronn deleted file mode 100644 index 598611c..0000000 --- a/doc/espeakup.8.ronn +++ /dev/null @@ -1,77 +0,0 @@ - - -# espeakup(8) --- connect Speakup to the espeak-ng TTS engine - -## SYNOPSIS - -`espeakup` [`--pid-path=`] [`--alsa-volume`] -[`--default-voice=`[]] [`--debug`] [`--help`] [`--version`] - -## OPTIONS - - * `-P` , `--pid-path=`: - Set the full path for the pid file espeakup uses when in daemon mode. - - * `--alsa-volume`: - Drive the ALSA volume. useful for live environments where volume - adjustments maybe impossible. - - * `-V` , `--default-voice=`: - Set the espeak-ng voice to be used by default. - - * `-d`, `--debug`: - run in the foreground, rather than becoming a daemon process. - - * `-h`, `--help`: - display a brief help message and exit. - - * `-v`, `--version`: - output version information and exit. - -## DESCRIPTION - -espeakup bridges the gap between two tools: the Speakup screen review system and -the espeak-ng text-to-speech engine. Each of these tools performs a -well-defined task. - -Speakup is a kernel-based screen reader for the Linux console. It extracts and -processes the text that is displayed on the foreground virtual console. It -supports several hardware based speech synthesizers directly. However, since it -is in kernel space, it cannot support a software speech synthesizer directly -since these are in user space. - -espeak-ng is a popular software speech synthesizer. It is small, light weight, -very responsive, and supports multiple languages. espeakup is a connector which -will read text sent to it by speakup and forward it to espeak-ng. This allows -Speakup to use espeak-ng as its speech synthesizer. - -espeakup is a daemon. Typically, it is started at boot time, and it terminates -when the system is halted or rebooted. It should be started by the system's init -scripts. This process varies among Linux distributions, but the details are -usually managed by the person who packaged espeakup for your distribution. From -the perspective of an average user, espeakup's operation is invisible. - -## BUGS - -If you find a bug, please create a -[github issue](https://github.com/linux-speakup/espeakup/issues) -You might also consider mentioning it on the mailing list for the Speakup -screenreader. Visit -[list page](https://linux-speakup.org/cgi-bin/mailman/listinfo/speakup) -to learn more about the mailing list. - -## SEE ALSO - -For more information about Speakup, visit its -[homepage](https://linux-speakup.org). - -espeak-ng can be found at [github](https://github.com/espeak-ng/espeak-ng) - -## AUTHOR - -William Hubbs is the author of espeakup. - -This manual page was written by Chris Brannon . - -current authors and maintainers can be found at -[github](https://github.com/linux-speakup/espeakup/graphs/contributors) diff --git a/doc/meson.build b/doc/meson.build deleted file mode 100644 index f055bb4..0000000 --- a/doc/meson.build +++ /dev/null @@ -1,8 +0,0 @@ -ronn = find_program('ronn', required: get_option('man')) -if ronn.found() - custom_target('man', - input : files('espeakup.8.ronn'), - output : 'espeakup.8', - command : [ronn, '--output-dir', '@OUTDIR@', '--roff', '@INPUT@'], - install : true, install_dir: join_paths(get_option('mandir'),'man8')) -endif diff --git a/espeak.c b/espeak.c new file mode 100644 index 0000000..f09d3c4 --- /dev/null +++ b/espeak.c @@ -0,0 +1,328 @@ +/* + * espeakup - interface which allows speakup to use espeak + * + * Copyright (C) 2008 William Hubbs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "espeakup.h" + +/* default voice settings */ +const int defaultFrequency = 5; +const int defaultPitch = 5; +const int defaultRate = 2; +const int defaultVolume = 5; +char *defaultVoice = NULL; + +/* multipliers and offsets */ +const int frequencyMultiplier = 11; +const int pitchMultiplier = 11; +const int rateMultiplier = 41; +const int rateOffset = 80; +const int volumeMultiplier = 22; + +volatile int stop_requested = 0; + +static int acsint_callback(short *wav, int numsamples, espeak_EVENT * events) +{ + int i; + for (i = 0; events[i].type != espeakEVENT_LIST_TERMINATED; i++) { + if (events[i].type == espeakEVENT_MARK) { + int mark = atoi(events[i].id.name); + if ((mark < 0) || (mark > 255)) + continue; + putchar(mark); + fflush(stdout); + } + } + return 0; +} + +static espeak_ERROR set_frequency(struct synth_t *s, int freq, + enum adjust_t adj) +{ + espeak_ERROR rc; + + if (adj == ADJ_DEC) + freq = -freq; + if (adj != ADJ_SET) + freq += s->frequency; + rc = espeak_SetParameter(espeakRANGE, freq * frequencyMultiplier, 0); + if (rc == EE_OK) + s->frequency = freq; + return rc; +} + +static espeak_ERROR set_pitch(struct synth_t *s, int pitch, + enum adjust_t adj) +{ + espeak_ERROR rc; + + if (adj == ADJ_DEC) + pitch = -pitch; + if (adj != ADJ_SET) + pitch += s->pitch; + rc = espeak_SetParameter(espeakPITCH, pitch * pitchMultiplier, 0); + if (rc == EE_OK) + s->pitch = pitch; + return rc; +} + +static espeak_ERROR set_punctuation(struct synth_t *s, int punct, + enum adjust_t adj) +{ + espeak_ERROR rc; + + if (adj == ADJ_DEC) + punct = -punct; + if (adj != ADJ_SET) + punct += s->punct; + rc = espeak_SetParameter(espeakPUNCTUATION, punct, 0); + if (rc == EE_OK) + s->punct = punct; + return rc; +} + +static espeak_ERROR set_rate(struct synth_t *s, int rate, + enum adjust_t adj) +{ + espeak_ERROR rc; + + if (adj == ADJ_DEC) + rate = -rate; + if (adj != ADJ_SET) + rate += s->rate; + rc = espeak_SetParameter(espeakRATE, + rate * rateMultiplier + rateOffset, 0); + if (rc == EE_OK) + s->rate = rate; + return rc; +} + +static espeak_ERROR set_voice(struct synth_t *s, char *voice) +{ + espeak_ERROR rc; + espeak_VOICE voice_select; + + rc = espeak_SetVoiceByName(voice); + if (rc != EE_OK) + { + memset(&voice_select, 0, sizeof(voice_select)); + voice_select.languages = voice; + rc = espeak_SetVoiceByProperties(&voice_select); + } + if (rc == EE_OK) + strcpy(s->voice, voice); + return rc; +} + +static espeak_ERROR set_volume(struct synth_t *s, int vol, + enum adjust_t adj) +{ + espeak_ERROR rc; + + if (adj == ADJ_DEC) + vol = -vol; + if (adj != ADJ_SET) + vol += s->volume; + rc = espeak_SetParameter(espeakVOLUME, (vol + 1) * volumeMultiplier, + 0); + if (rc == EE_OK) + s->volume = vol; + + return rc; +} + +static espeak_ERROR stop_speech(void) +{ + espeak_ERROR rc; + + rc = espeak_Cancel(); + return rc; +} + +static espeak_ERROR speak_text(struct synth_t *s) +{ + espeak_ERROR rc; + int synth_mode = 0; + + if (espeakup_mode == ESPEAKUP_MODE_ACSINT) + synth_mode |= espeakSSML; + + if (espeakup_mode == ESPEAKUP_MODE_SPEAKUP && (s->len == 1)) { + char *buf; + int n; + n = asprintf(&buf, + "%c", + s->buf[0]); + if (n == -1) { + /* D'oh. Not much to do on allocation failure. + * Perhaps espeak will happen to say the character */ + rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, + 0, synth_mode, NULL, NULL); + } else { + rc = espeak_Synth(buf, n + 1, 0, POS_CHARACTER, 0, + espeakSSML, NULL, NULL); + free(buf); + } + } else + rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, + synth_mode, NULL, NULL); + return rc; +} + +static void free_espeak_entry(struct espeak_entry_t *entry) +{ + assert(entry); + if (entry->cmd == CMD_SPEAK_TEXT) + free(entry->buf); + free(entry); +} + +static void synth_queue_clear() +{ + struct espeak_entry_t *current; + + while (queue_peek(synth_queue)) { + current = (struct espeak_entry_t *) queue_remove(synth_queue); + free_espeak_entry(current); + } +} + +static void queue_process_entry(struct synth_t *s) +{ + espeak_ERROR error; + static struct espeak_entry_t *current = NULL; + + if (current != queue_peek(synth_queue)) { + if (current) + free_espeak_entry(current); + current = (struct espeak_entry_t *) queue_remove(synth_queue); + } + pthread_mutex_unlock(&queue_guard); + switch (current->cmd) { + case CMD_SET_FREQUENCY: + error = set_frequency(s, current->value, current->adjust); + break; + case CMD_SET_PITCH: + error = set_pitch(s, current->value, current->adjust); + break; + case CMD_SET_PUNCTUATION: + error = set_punctuation(s, current->value, current->adjust); + break; + case CMD_SET_RATE: + error = set_rate(s, current->value, current->adjust); + break; + case CMD_SET_VOICE: + error = EE_OK; + break; + case CMD_SET_VOLUME: + error = set_volume(s, current->value, current->adjust); + break; + case CMD_SPEAK_TEXT: + s->buf = current->buf; + s->len = current->len; + error = speak_text(s); + break; + default: + break; + } + + if (error == EE_OK) { + free_espeak_entry(current); + current = NULL; + } +} + +int initialize_espeak(struct synth_t *s) +{ + int rate; + + /* initialize espeak */ + rate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 50, NULL, 0); + if (rate < 0) { + fprintf(stderr, "Unable to initialize espeak.\n"); + return -1; + } + + /* We need a callback in acsint mode, but not in speakup mode. */ + if (espeakup_mode == ESPEAKUP_MODE_ACSINT) + espeak_SetSynthCallback(acsint_callback); + + /* Setup initial voice parameters */ + if (defaultVoice) { + set_voice(s, defaultVoice); + free(defaultVoice); + defaultVoice = NULL; + } + set_frequency(s, defaultFrequency, ADJ_SET); + set_pitch(s, defaultPitch, ADJ_SET); + set_rate(s, defaultRate, ADJ_SET); + set_volume(s, defaultVolume, ADJ_SET); + espeak_SetParameter(espeakCAPITALS, 0, 0); + return 0; +} + +/* espeak_thread is the "main" function of our secondary (queue-processing) + * thread. + * First, lock queue_guard, because it needs to be locked when we call + * pthread_cond_wait on the runner_awake condition variable. + * Next, enter an infinite loop. + * The wait call also unlocks queue_guard, so that the other thread can + * manipulate the queue. + * When runner_awake is signaled, the pthread_cond_wait call re-locks + * queue_guard, and the "queue processor" thread has access to the queue. + * While there is an entry in the queue, call queue_process_entry. + * queue_process_entry unlocks queue_guard after removing an item from the + * queue, so that the main thread doesn't have to wait for us to finish + * processing the entry. So re-lock queue_guard after each call to + * queue_process_entry. + * + * The main thread can add items to the queue in exactly two situations: + * 1. We are waiting on runner_awake, or + * 2. We are processing an entry that has just been removed from the queue. +*/ +void *espeak_thread(void *arg) +{ + struct synth_t *s = (struct synth_t *) arg; + + pthread_mutex_lock(&queue_guard); + while (should_run) { + + while (should_run && !queue_peek(synth_queue) && !stop_requested) + pthread_cond_wait(&runner_awake, &queue_guard); + + if (stop_requested) { + stop_speech(); + synth_queue_clear(); + stop_requested = 0; + pthread_cond_signal(&stop_acknowledged); + } + + while (should_run && queue_peek(synth_queue) && !stop_requested) { + queue_process_entry(s); + pthread_mutex_lock(&queue_guard); + } + } + pthread_cond_signal(&stop_acknowledged); + pthread_mutex_unlock(&queue_guard); + return NULL; +} diff --git a/espeakup.8 b/espeakup.8 new file mode 100644 index 0000000..092c776 --- /dev/null +++ b/espeakup.8 @@ -0,0 +1,78 @@ +.\" Hey, Emacs! This is an -*- nroff -*- source file. +.\" Espeakup is Copyright 2008 by William Hubbs. +.\" This is free software; see the GNU General Public Licence version 3 +.\" or later for copying conditions. There is NO warranty. +.TH ESPEAKUP 8 "5 Nov 2008" "0.60" +.nh +.SH NAME +espeakup \(em connect Speakup to the ESpeak TTS engine +.SH SYNOPSIS +.B espeakup +[ +.B \-\^\-pid-path=path +] +[ +.B \-\^\-default-voice=voicename +] +[ +.B \-\^\-debug +] +[ +.B \-\^\-help +] +[ +.B \-\^\-version +] +.SH OPTIONS +.TP +.B \-P path, \-\^\-pid-path=path +Set the full path for the pid file espeakup uses when in daemon mode. +.TP +.B \-V voicename, \-\^\-default-voice=voicename +Set the espeak voice to be used by default. +.TP +.B \-d, \-\^\-debug +run in the foreground, rather than becoming a daemon process. +.TP +.B \-h, \-\^\-help +display a brief help message and exit. +.TP +.B \-v, \-\^\-version +output version information and exit. +.SH DESCRIPTION +Espeakup bridges the gap between two tools: the Speakup screen review +system and the ESppeak text-to-speech engine. Each of these tools +performs a well-defined task. Speakup is a kernel-based screen reader +for the Linux console. It extracts and processes the text that is +displayed on the foreground virtual console. It supports several +hardware based speech synthesizers directly. However, since it is in +kernel space, it cannot support a software speech synthesizer directly +since these are in user space. +ESpeak is a popular software speech synthesizer. It is small, light +weight, very responsive, and supports multiple languages. +Espeakup is a connector which will read text sent to it by speakup and +forward it to ESpeak. This allows Speakup to use ESpeak as its speech +synthesizer. +.PP +Espeakup is a daemon. Typically, it is started at boot time, and it terminates +when the system is halted or rebooted. It should be started by the +system's init scripts. This process varies among Linux distributions, +but the details are usually managed by the person who packaged Espeakup for +your distribution. +From the perspective of an average user, Espeakup's operation is invisible. +.SH BUGS +.PP +Espeakup is still classified as alpha software. Bugs are periodically found +and fixed. If you find a bug, please do report it to the author. You +might also consider mentioning it on the mailing list for the Speakup +screenreader. Visit http://speech.braille.uwo.ca/mailman/listinfo/speakup +to learn more about the mailing list. +.SH SEE ALSO +.PP +For more information about Speakup, visit its homepage: http://linux-speakup.org. +ESpeak's home page is http://espeak.sourceforge.net. +.SH AUTHOR +.PP +William Hubbs is the author and maintainer of Espeakup. He may be reached +via the email address . This manual page was written +by Chris Brannon, and his email address is . diff --git a/src/espeakup.c b/espeakup.c similarity index 74% rename from src/espeakup.c rename to espeakup.c index 4e077f5..1981430 100644 --- a/src/espeakup.c +++ b/espeakup.c @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2008 William Hubbs * @@ -18,18 +18,17 @@ */ #include -#include #include #include #include #include -#include -#include #include +#include +#include #include "espeakup.h" -// path to our pid file +/* path to our pid file */ char *pidPath = "/var/run/espeakup.pid"; int debug = 0; @@ -41,9 +40,7 @@ volatile int should_run = 1; espeak_AUDIO_OUTPUT audio_mode; pthread_cond_t runner_awake = PTHREAD_COND_INITIALIZER; -/* Initialized in main: use the monotonic clock for timed waits. */ -pthread_cond_t wake_stop; -pthread_cond_t stop_acknowledged; +pthread_cond_t stop_acknowledged = PTHREAD_COND_INITIALIZER; pthread_mutex_t queue_guard = PTHREAD_MUTEX_INITIALIZER; int espeakup_start_daemon(void) @@ -63,7 +60,7 @@ int espeakup_start_daemon(void) exit(1); } if (pid) { - // Parent, just wait for daemon + /* Parent, just wait for daemon */ if (read(fds[0], &c, 1) < 0) { printf("Espeakup is already running!\n"); exit(1); @@ -71,17 +68,17 @@ int espeakup_start_daemon(void) exit(c); } - // Child, create new session + /* Child, create new session */ setsid(); pid = fork(); if (pid) - // Intermediate child, just exit + /* Intermediate child, just exit */ exit(0); - // Child + /* Child */ if (chdir("/") < 0) { c = 1; - (void) write(fds[1], &c, 1); + (void)write(fds[1], &c, 1); exit(1); } return fds[1]; @@ -102,18 +99,20 @@ int espeakup_is_running(void) } if (flock(pidFile, LOCK_EX) < 0) { - printf("Can not lock the pid file %s: %s\n", pidPath, strerror(errno)); + printf("Can not lock the pid file %s: %s\n", pidPath, + strerror(errno)); goto error; } n = read(pidFile, s, sizeof(s) - 1); if (n < 0) { - printf("Can not read the pid file %s: %s\n", pidPath, strerror(errno)); + printf("Can not read the pid file %s: %s\n", pidPath, + strerror(errno)); goto error; } s[n] = 0; n = sscanf(s, "%d", &pid); if (n == 1 && (!kill(pid, 0) || errno != ESRCH)) { - // Already running + /* Already running */ close(pidFile); return 1; } @@ -149,18 +148,6 @@ int main(int argc, char **argv) struct synth_t s = { .voice = "", }; - pthread_condattr_t monotonic_attr; - - /* Condition variables used with pthread_cond_timedwait must use the - * monotonic clock, so that wall-clock adjustments (NTP, an - * installer setting the system time) cannot make the timeouts fire - * too early or far too late. */ - pthread_condattr_init(&monotonic_attr); - pthread_condattr_setclock(&monotonic_attr, CLOCK_MONOTONIC); - pthread_cond_init(&wake_stop, &monotonic_attr); - pthread_cond_init(&stop_acknowledged, &monotonic_attr); - pthread_condattr_destroy(&monotonic_attr); - synth_queue = new_queue(); if (!synth_queue) { @@ -168,13 +155,13 @@ int main(int argc, char **argv) return 2; } - // set up the pipe used to wake the espeak thread + /* set up the pipe used to wake the espeak thread */ if (pipe(self_pipe_fds) < 0) { perror("Unable to create pipe"); return 5; } - // process command line options + /* process command line options */ process_cli(argc, argv); if (!debug && espeakup_mode == ESPEAKUP_MODE_SPEAKUP) { @@ -194,7 +181,7 @@ int main(int argc, char **argv) close(devnull); } - // create the signal processing thread here. + /* create the signal processing thread here. */ err = pthread_create(&signal_thread_id, NULL, signal_thread, NULL); if (err != 0) { ret = 4; @@ -210,26 +197,26 @@ int main(int argc, char **argv) sigaddset(&sigset, SIGTERM); sigprocmask(SIG_BLOCK, &sigset, NULL); - // Initialize espeak +/* Initialize espeak */ if (initialize_espeak(&s) < 0) { ret = 2; goto out; } - // open the softsynth +/* open the softsynth */ if (open_softsynth() < 0) { ret = 2; goto out; } - // Spawn our softsynth thread. + /* Spawn our softsynth thread. */ err = pthread_create(&softsynth_thread_id, NULL, softsynth_thread, &s); if (err != 0) { ret = 4; goto out; } - // Spawn our espeak-interacting thread. + /* Spawn our espeak-interacting thread. */ err = pthread_create(&espeak_thread_id, NULL, espeak_thread, &s); if (err != 0) { ret = 4; @@ -237,15 +224,14 @@ int main(int argc, char **argv) } if (!debug && espeakup_mode == ESPEAKUP_MODE_SPEAKUP) - (void) write(fd, &ret, 1); + (void)write(fd, &ret, 1); - // wait for the threads to shut down. + /* wait for the threads to shut down. */ pthread_join(signal_thread_id, NULL); pthread_join(softsynth_thread_id, NULL); pthread_join(espeak_thread_id, NULL); - if (!paused_espeak) - espeak_Terminate(); + espeak_Terminate(); close_softsynth(); out: @@ -253,8 +239,9 @@ out: if (ret != 1) unlink(pidPath); if (ret != 0) - (void) write(fd, &ret, 1); - // If ret was 0, the status byte was written before joining the threads. + (void)write(fd, &ret, 1); + /* If ret was 0, the status byte was written before joining + * the threads. */ } return ret; } diff --git a/src/espeakup.h b/espeakup.h similarity index 81% rename from src/espeakup.h rename to espeakup.h index 62a5ca8..4d1bcf7 100644 --- a/src/espeakup.h +++ b/espeakup.h @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2008 William Hubbs * @@ -20,40 +20,35 @@ #ifndef __ESPEAKUP_H #define __ESPEAKUP_H -// This was added for gcc 4.3 -#include +/* This was added for gcc 4.3 */ #include +#include -#include +#include #include "queue.h" -#define PACKAGE_BUGREPORT "https://github.com/linux-speakup/espeakup/issues" +#define PACKAGE_VERSION "0.80" +#define PACKAGE_BUGREPORT "http://github.com/williamh/espeakup/issues" -enum espeakup_mode_t -{ +enum espeakup_mode_t { ESPEAKUP_MODE_SPEAKUP, ESPEAKUP_MODE_ACSINT }; -enum command_t -{ +enum command_t { CMD_SET_FREQUENCY, - CMD_SET_MARK, CMD_SET_PITCH, - CMD_SET_RANGE, CMD_SET_PUNCTUATION, CMD_SET_RATE, CMD_SET_VOICE, CMD_SET_VOLUME, CMD_SPEAK_TEXT, CMD_FLUSH, - CMD_PAUSE, CMD_UNKNOWN, }; -enum adjust_t -{ +enum adjust_t { ADJ_DEC, ADJ_SET, ADJ_INC, @@ -70,10 +65,9 @@ struct espeak_entry_t { struct synth_t { int frequency; int pitch; - int range; int punct; int rate; - char voice[20]; + char voice[10]; int volume; char *buf; int len; @@ -90,16 +84,13 @@ extern void *espeak_thread(void *arg); extern int open_softsynth(void); extern void close_softsynth(void); extern void *softsynth_thread(void *arg); -extern void softsynth_reportindex(int index); extern volatile int should_run; extern volatile int stop_requested; -extern int paused_espeak; extern int self_pipe_fds[2]; #define PIPE_READ_FD (self_pipe_fds[0]) #define PIPE_WRITE_FD (self_pipe_fds[1]) extern pthread_cond_t runner_awake; -extern pthread_cond_t wake_stop; extern pthread_cond_t stop_acknowledged; extern pthread_mutex_t queue_guard; diff --git a/meson.build b/meson.build deleted file mode 100644 index 38788d2..0000000 --- a/meson.build +++ /dev/null @@ -1,25 +0,0 @@ -project('espeakup', 'c', - default_options : [ - 'buildtype=debugoptimized', - 'c_std=gnu11', - 'warning_level=3' - ], - license : 'GPL-3.0-or-later', - version : '0.90', - meson_version : '>=0.51.0') - -cc = meson.get_compiler('c') -thread_dep = dependency('threads') -espeak_dep = dependency('espeak-ng') -alsa_dep = dependency('alsa') -math_dep = cc.find_library('m', required : false) - -subdir('doc') -subdir('services') -subdir('src') - -executable('espeakup', - espeakup_version, - espeakup_sources, - dependencies : [thread_dep, espeak_dep, alsa_dep, math_dep], - install : true) diff --git a/meson_options.txt b/meson_options.txt deleted file mode 100644 index c8560b6..0000000 --- a/meson_options.txt +++ /dev/null @@ -1,4 +0,0 @@ -option('man', type : 'feature', value : 'auto', - description : 'build manpage with ronn') -option('systemd', type : 'feature', value : 'auto', - description :'enable systemd support') diff --git a/src/queue.c b/queue.c similarity index 96% rename from src/queue.c rename to queue.c index 63a5527..860ad94 100644 --- a/src/queue.c +++ b/queue.c @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Note that these functions are meant to be used in either a single or * multi-threaded environment, so they know nothing about mutexes, etc. diff --git a/src/queue.h b/queue.h similarity index 90% rename from src/queue.h rename to queue.h index a1a2a99..249f3ba 100644 --- a/src/queue.h +++ b/queue.h @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2008 William Hubbs * @@ -20,7 +20,7 @@ #ifndef __QUEUE_H #define __QUEUE_H -struct queue_t; // An opaque type. +struct queue_t; /* An opaque type. */ extern struct queue_t *new_queue(void); extern int queue_add(struct queue_t *q, void *entry); diff --git a/services/meson.build b/services/meson.build deleted file mode 100644 index 5eadcac..0000000 --- a/services/meson.build +++ /dev/null @@ -1,4 +0,0 @@ -systemd = dependency('systemd') -if (systemd.found() and get_option('systemd').allowed()) or get_option('systemd').enabled() - subdir('systemd') -endif diff --git a/services/systemd/espeakup.service.in b/services/systemd/espeakup.service.in deleted file mode 100644 index 075a717..0000000 --- a/services/systemd/espeakup.service.in +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Software speech output for Speakup -Documentation=man:espeakup(8) -Wants=modprobe@speakup_soft.service -After=modprobe@speakup_soft.service sound.target - -[Service] -Type=forking -PIDFile=/run/espeakup.pid -Environment="default_voice=" -ExecStart=@bindir@/espeakup --default-voice=${default_voice} -ExecReload=kill -HUP $MAINPID -Restart=always -Nice=-10 -OOMScoreAdjust=-900 - -[Install] -WantedBy=sound.target diff --git a/services/systemd/meson.build b/services/systemd/meson.build deleted file mode 100644 index 1a15303..0000000 --- a/services/systemd/meson.build +++ /dev/null @@ -1,20 +0,0 @@ -if systemd.found() - unitdir = systemd.get_variable(pkgconfig: 'systemdsystemunitdir') -else - unitdir = join_paths(prefixdir, get_option('libdir'), 'systemd', 'system') -endif -prefixdir = get_option('prefix') -bindir = join_paths(prefixdir, get_option('bindir')) - -unit_conf = configuration_data() -unit_conf.set('bindir', bindir) - -service_file = configure_file( - input : 'espeakup.service.in', - output : 'espeakup.service', - configuration : unit_conf -) - -install_data(service_file, - install_dir : unitdir -) diff --git a/src/signal.c b/signal.c similarity index 70% rename from src/signal.c rename to signal.c index b6ddefc..102c3cf 100644 --- a/src/signal.c +++ b/signal.c @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2008 William Hubbs * @@ -21,11 +21,10 @@ #include #include #include +#define STOP_MSG "s" #include "espeakup.h" -#define STOP_MSG "s" - /* * We install a dummy signal handler to let the o/s know that we * do not want the default action to be performed since we are @@ -41,8 +40,8 @@ void *signal_thread(void *arg) sigset_t sigset; int sig; - memset(&temp, 0, sizeof(struct sigaction)); - // install dummy handlers for the signals we want to process + memset(&temp, 0, sizeof (struct sigaction)); + /* install dummy handlers for the signals we want to process */ temp.sa_handler = dummy_handler; sigemptyset(&temp.sa_mask); sigaction(SIGINT, &temp, NULL); @@ -58,24 +57,14 @@ void *signal_thread(void *arg) case SIGTERM: pthread_mutex_lock(&queue_guard); should_run = 0; - /* Wake up any thread waiting on a condition variable so - * that it notices the shutdown request: the softsynth - * thread may be waiting for a stop acknowledgement, and - * the espeak thread may be waiting for work or throttling - * before a retry. */ - pthread_cond_broadcast(&runner_awake); - pthread_cond_broadcast(&wake_stop); - pthread_cond_broadcast(&stop_acknowledged); pthread_mutex_unlock(&queue_guard); break; default: printf("espeakup caught signal %d\n", sig); break; } - pthread_mutex_lock(&queue_guard); } - pthread_mutex_unlock(&queue_guard); - // Tell the reader to stop, if it is in a select() call. + /* Tell the reader to stop, if it is in a select() call. */ write(PIPE_WRITE_FD, STOP_MSG, strlen(STOP_MSG)); return NULL; } diff --git a/src/softsynth.c b/softsynth.c similarity index 70% rename from src/softsynth.c rename to softsynth.c index e382b32..3394434 100644 --- a/src/softsynth.c +++ b/softsynth.c @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2008 William Hubbs * @@ -17,28 +17,27 @@ * along with this program. If not, see . */ -#include #include #include #include #include -#include -#include -#include #include +#include +#include +#include #include "espeakup.h" #include "stringhandling.h" -// max buffer size +/* max buffer size */ static const size_t maxBufferSize = 16 * 1024 + 1; -// synth flush character +/* synth flush character */ static const int synthFlushChar = 0x18; static int softFD = 0; -// Text accumulator: +/* Text accumulator: */ char *textAccumulator; int textAccumulator_l; @@ -125,24 +124,15 @@ static int process_command(struct synth_t *s, char *buf, int start) case 'f': cmd = CMD_SET_FREQUENCY; break; - case 'i': - cmd = CMD_SET_MARK; - break; case 'p': cmd = CMD_SET_PITCH; break; - case 'r': - cmd = CMD_SET_RANGE; - break; case 's': cmd = CMD_SET_RATE; break; case 'v': cmd = CMD_SET_VOLUME; break; - case 'P': - cmd = CMD_PAUSE; - break; default: cmd = CMD_UNKNOWN; break; @@ -156,7 +146,8 @@ static int process_command(struct synth_t *s, char *buf, int start) } if (cmd != CMD_FLUSH && cmd != CMD_UNKNOWN) { - if (espeakup_mode == ESPEAKUP_MODE_ACSINT && textAccumulator_l != 0) { + if (espeakup_mode == ESPEAKUP_MODE_ACSINT + && textAccumulator_l != 0) { queue_add_text(textAccumulator, textAccumulator_l); free(textAccumulator); textAccumulator = initString(&textAccumulator_l); @@ -177,8 +168,7 @@ static void process_buffer(struct synth_t *s, char *buf, ssize_t length) start = 0; end = 0; while (start < length) { - while ((buf[end] < 0 || buf[end] >= ' ' || buf[end] == '\n') && - end < length) + while ((buf[end] < 0 || buf[end] >= ' ') && end < length) end++; if (end != start) { txtLen = end - start; @@ -193,7 +183,8 @@ static void process_buffer(struct synth_t *s, char *buf, ssize_t length) } } -static void process_buffer_acsint(struct synth_t *s, char *buf, ssize_t length) +static void process_buffer_acsint(struct synth_t *s, char *buf, + ssize_t length) { int start = 0; int i; @@ -207,8 +198,8 @@ static void process_buffer_acsint(struct synth_t *s, char *buf, ssize_t length) break; } if (i > start) - stringAndBytes(&textAccumulator, &textAccumulator_l, buf + start, - i - start); + stringAndBytes(&textAccumulator, &textAccumulator_l, + buf + start, i - start); if (flushIt) { if (textAccumulator != EMPTYSTRING) { queue_add_text(textAccumulator, textAccumulator_l); @@ -224,56 +215,29 @@ static void process_buffer_acsint(struct synth_t *s, char *buf, ssize_t length) } } -/* How long to wait for the espeak thread to acknowledge a stop request - * before concluding that espeak is wedged beyond in-process recovery. */ -static const int stopAckTimeout = 10; - static void request_espeak_stop(void) { - struct timespec timeout; - int err = 0; - pthread_mutex_lock(&queue_guard); stop_requested = 1; - pthread_cond_signal(&runner_awake); // Wake runner, if necessary. - pthread_cond_signal(&wake_stop); // Wake runner, if necessary. - clock_gettime(CLOCK_MONOTONIC, &timeout); - timeout.tv_sec += stopAckTimeout; - while (should_run && stop_requested && err != ETIMEDOUT) - // wait for acknowledgement. - err = pthread_cond_timedwait(&stop_acknowledged, &queue_guard, - &timeout); - if (should_run && stop_requested) { - /* The espeak thread is stuck in a call into espeak, most likely - * on a wedged audio device. There is no way to recover from - * within the process: exit so that the init system can respawn - * us in a clean state, rather than staying silent, ignoring - * SIGTERM, and stalling the whole console by not draining - * /dev/softsynth anymore. Use _exit because exit could hang in - * library destructors while the audio device is wedged. */ - fprintf(stderr, "espeakup: espeak did not acknowledge a stop " - "request within %d seconds, aborting\n", stopAckTimeout); - _exit(3); - } + pthread_cond_signal(&runner_awake); /* Wake runner, if necessary. */ + while (should_run && stop_requested) + pthread_cond_wait(&stop_acknowledged, &queue_guard); /* wait for acknowledgement. */ pthread_mutex_unlock(&queue_guard); } int open_softsynth(void) { int rc = 0; - // If we're in acsint mode, we read from stdin. No need to open. + /* If we're in acsint mode, we read from stdin. No need to open. */ if (espeakup_mode == ESPEAKUP_MODE_ACSINT) { softFD = STDIN_FILENO; return 0; } - // open the softsynth. - softFD = open("/dev/softsynthu", O_RDWR | O_NONBLOCK); - if (softFD < 0 && errno == ENOENT) - // Kernel without unicode support? Try without unicode. - softFD = open("/dev/softsynth", O_RDWR | O_NONBLOCK); + /* open the softsynth. */ + softFD = open("/dev/softsynth", O_RDWR | O_NONBLOCK); if (softFD < 0) { - perror("Unable to open the /dev/softsynth device"); + perror("Unable to open the softsynth device"); rc = -1; } return rc; @@ -355,16 +319,3 @@ void *softsynth_thread(void *arg) pthread_mutex_unlock(&queue_guard); return NULL; } - -void softsynth_reportindex(int index) -{ - if (espeakup_mode == ESPEAKUP_MODE_ACSINT) { - putchar(index); - fflush(stdout); - } else { - char buf[16]; - snprintf(buf, sizeof(buf), "%d", index); - if (write(softFD, buf, strlen(buf)) < 0) - perror("Writing index failed"); - } -} diff --git a/src/espeak.c b/src/espeak.c deleted file mode 100644 index c9ac908..0000000 --- a/src/espeak.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * espeakup - interface which allows speakup to use espeak-ng - * - * Copyright (C) 2008 William Hubbs - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "espeakup.h" - -/* default voice settings */ -const int defaultFrequency = 5; -const int defaultPitch = 5; -const int defaultRange = 5; -const int defaultRate = 2; -const int defaultVolume = 5; -char *defaultVoice = NULL; -int alsaVolume = 0; - -/* multipliers and offsets */ -const int frequencyMultiplier = 11; -const int pitchMultiplier = 11; -const int rangeMultiplier = 11; -const int rateMultiplier = 41; -const int rateOffset = 80; -const int volumeMultiplier = 22; - -volatile int stop_requested = 0; -int paused_espeak = 1; - -/* Wedged-engine detection. Espeak may legitimately refuse entries for a - * while (EE_BUFFER_FULL while a long backlog is being played back), so a - * failing entry is normally just retried. But when entries keep failing - * while the synth callback reports no progress at all, the audio output - * is most likely wedged (e.g. an ALSA device stuck returning EBUSY). - * After ESPEAK_STALL_RETRIES consecutive such retries (about one second - * each), restart the engine; after ESPEAK_MAX_RESTARTS restarts without - * the engine having been healthy for ESPEAK_HEALTHY_SECS in between, - * give up and exit, so that the init system can respawn us. */ -#define ESPEAK_STALL_RETRIES 10 -#define ESPEAK_MAX_RESTARTS 3 -#define ESPEAK_HEALTHY_SECS 60 - -/* Set by the synth callback whenever espeak makes synthesis progress; - * used to tell a merely backlogged engine from a wedged one. The - * callback runs in espeak's own thread, so the flag is atomic. */ -static atomic_int synth_progressed = 0; -static int stalled_retries = 0; -static int restart_attempts = 0; -static struct timespec last_restart; - -static int callback(short *wav, int numsamples, espeak_EVENT *events) -{ - int i; - atomic_store(&synth_progressed, 1); - for (i = 0; events[i].type != espeakEVENT_LIST_TERMINATED; i++) { - if (events[i].type == espeakEVENT_MARK) { - int mark = atoi(events[i].id.name); - if ((mark < 0) || (mark > 255)) - continue; - softsynth_reportindex(mark); - } - } - return 0; -} - -static espeak_ERROR set_frequency(struct synth_t *s, int freq, - enum adjust_t adj) -{ - espeak_ERROR rc; - - if (adj == ADJ_DEC) - freq = -freq; - if (adj != ADJ_SET) - freq += s->frequency; - rc = espeak_SetParameter(espeakRANGE, freq * frequencyMultiplier, 0); - if (rc == EE_OK) - s->frequency = freq; - return rc; -} - -static espeak_ERROR set_pitch(struct synth_t *s, int pitch, enum adjust_t adj) -{ - espeak_ERROR rc; - - if (adj == ADJ_DEC) - pitch = -pitch; - if (adj != ADJ_SET) - pitch += s->pitch; - rc = espeak_SetParameter(espeakPITCH, pitch * pitchMultiplier, 0); - if (rc == EE_OK) - s->pitch = pitch; - return rc; -} - -static espeak_ERROR set_range(struct synth_t *s, int range, enum adjust_t adj) -{ - espeak_ERROR rc; - - if (adj == ADJ_DEC) - range = -range; - if (adj != ADJ_SET) - range += s->range; - rc = espeak_SetParameter(espeakRANGE, range * rangeMultiplier, 0); - if (rc == EE_OK) - s->range = range; - return rc; -} - -static espeak_ERROR set_punctuation(struct synth_t *s, int punct, - enum adjust_t adj) -{ - espeak_ERROR rc; - espeak_PUNCT_TYPE espeak_punct; - - if (adj == ADJ_DEC) - punct = -punct; - if (adj != ADJ_SET) - punct += s->punct; - - switch (punct) { - case 0: - espeak_punct = espeakPUNCT_NONE; - break; - case 1: - espeak_punct = espeakPUNCT_SOME; - break; - case 2: - /* XXX: approximation */ - espeak_punct = espeakPUNCT_SOME; - break; - case 3: - default: - espeak_punct = espeakPUNCT_ALL; - break; - } - - rc = espeak_SetParameter(espeakPUNCTUATION, espeak_punct, 0); - if (rc == EE_OK) - s->punct = punct; - return rc; -} - -static espeak_ERROR set_rate(struct synth_t *s, int rate, enum adjust_t adj) -{ - espeak_ERROR rc; - - if (adj == ADJ_DEC) - rate = -rate; - if (adj != ADJ_SET) - rate += s->rate; - rc = espeak_SetParameter(espeakRATE, rate * rateMultiplier + rateOffset, 0); - if (rc == EE_OK) - s->rate = rate; - return rc; -} - -static espeak_ERROR set_voice(struct synth_t *s, char *voice) -{ - espeak_ERROR rc; - espeak_VOICE voice_select; - - rc = espeak_SetVoiceByName(voice); - if (rc != EE_OK) { - memset(&voice_select, 0, sizeof(voice_select)); - voice_select.languages = voice; - rc = espeak_SetVoiceByProperties(&voice_select); - } - if (rc == EE_OK) - strcpy(s->voice, voice); - return rc; -} - -static void set_alsa_volume(int vol) -{ - snd_mixer_t *m; - snd_mixer_elem_t *e; - int err; - - err = snd_mixer_open(&m, 0); - if (err < 0) { - fprintf(stderr, "ALSA mixer open error: %s\n", snd_strerror(err)); - return; - } - - err = snd_mixer_attach(m, "default"); - if (err < 0) { - fprintf(stderr, "ALSA mixer attach error: %s\n", snd_strerror(err)); - return; - } - err = snd_mixer_selem_register(m, NULL, NULL); - if (err < 0) { - fprintf(stderr, "ALSA mixer load error: %s\n", snd_strerror(err)); - return; - } - err = snd_mixer_load(m); - if (err < 0) { - fprintf(stderr, "ALSA mixer load error: %s\n", snd_strerror(err)); - return; - } - - /* Turn vol value to volume %. - * We do not want to soften that much with ALSA, espeak is already - * doing it. We want the default value (5) to be the usual default - * volume (80%), and make higher values increase ALSA volume, up to - * 100%. */ - - int volume = (vol + 1) * 50 / 10 + 50; - - for (e = snd_mixer_first_elem(m); e; e = snd_mixer_elem_next(e)) { - if (snd_mixer_elem_get_type(e) != SND_MIXER_ELEM_SIMPLE) - continue; - if (snd_mixer_selem_is_enumerated(e)) - continue; - - if (snd_mixer_selem_has_playback_switch(e)) { - snd_mixer_selem_set_playback_switch_all(e, 1); - } - - if (snd_mixer_selem_has_playback_volume(e)) { - long min, max, set; - - err = snd_mixer_selem_get_playback_dB_range(e, &min, &max); - if (err == 0 && min < max) { - if (max - min < 2400) { - /* 24dB amplitude is too small for using a logscale */ - set = min + volume * (max - min) / 100; - } else { - /* Use a logscale */ - double volf = volume / 100.; - if (min != SND_CTL_TLV_DB_GAIN_MUTE) { - double minf = pow(10, (min - max) / 6000.); - volf = volf * (1 - minf) + minf; - } - set = 6000. * log10(volf) + max; - } - snd_mixer_selem_set_playback_dB_all(e, set, 0); - } else { - /* No dB setting, try a linear scale */ - snd_mixer_selem_get_playback_volume_range(e, &min, &max); - set = min + volume * (max - min) / 100; - snd_mixer_selem_set_playback_volume_all(e, set); - } - } - } -} - -static espeak_ERROR set_volume(struct synth_t *s, int vol, enum adjust_t adj) -{ - espeak_ERROR rc; - - if (adj == ADJ_DEC) - vol = -vol; - if (adj != ADJ_SET) - vol += s->volume; - rc = espeak_SetParameter(espeakVOLUME, (vol + 1) * volumeMultiplier, 0); - if (rc == EE_OK) { - s->volume = vol; - if (alsaVolume) - set_alsa_volume(vol); - } - - return rc; -} - -static espeak_ERROR stop_speech(void) -{ - espeak_ERROR rc; - - rc = espeak_Cancel(); - return rc; -} - -static espeak_ERROR speak_text(struct synth_t *s) -{ - espeak_ERROR rc; - int synth_mode = 0; - - if (espeakup_mode == ESPEAKUP_MODE_ACSINT) - synth_mode |= espeakSSML; - - if (espeakup_mode == ESPEAKUP_MODE_SPEAKUP && (s->len == 1)) { - char *buf = NULL; - int n; - unsigned char c = s->buf[0]; - if (c == ' ') - n = asprintf(&buf, - " "); - else if (c < 0x20 || c > 0x7e) { - /* Not a printable character; do not embed it in SSML, as - * that would produce invalid markup. Fall through to the - * raw-synthesis path below. */ - n = -1; - } else { - /* Escape characters that are special in XML/SSML so the - * resulting markup stays well-formed; otherwise espeak-ng - * misparses the element, which is the source of - * the spurious high-pitched "ringing" on these characters. */ - const char *entity = NULL; - switch (c) { - case '<': entity = "<"; break; - case '>': entity = ">"; break; - case '&': entity = "&"; break; - case '\'': entity = "'"; break; - case '"': entity = """; break; - } - if (entity) - n = asprintf(&buf, - "%s", - entity); - else - n = asprintf(&buf, - "%c", - c); - } - if (n == -1) { - /* D'oh. Not much to do on allocation failure. - * Perhaps espeak will happen to say the character */ - rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, - synth_mode, NULL, NULL); - } else { - rc = espeak_Synth(buf, n + 1, 0, POS_CHARACTER, 0, espeakSSML, NULL, - NULL); - free(buf); - } - } else - rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, synth_mode, - NULL, NULL); - return rc; -} - -static void free_espeak_entry(struct espeak_entry_t *entry) -{ - assert(entry); - if (entry->cmd == CMD_SPEAK_TEXT) - free(entry->buf); - free(entry); -} - -static void synth_queue_clear() -{ - struct espeak_entry_t *current; - - while (queue_peek(synth_queue)) { - current = (struct espeak_entry_t *) queue_remove(synth_queue); - free_espeak_entry(current); - } -} - -static int reinitialize_espeak(struct synth_t *s) -{ - int rate; - - /* Re-initialize espeak */ - rate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0); - if (rate < 0) { - fprintf(stderr, "Unable to initialize espeak.\n"); - return -1; - } - - espeak_SetSynthCallback(callback); - - /* Set parameters again */ - espeak_SetVoiceByName(s->voice); - espeak_SetParameter(espeakRANGE, s->frequency * frequencyMultiplier, 0); - espeak_SetParameter(espeakPITCH, s->pitch * pitchMultiplier, 0); - espeak_SetParameter(espeakRATE, s->rate * rateMultiplier + rateOffset, 0); - espeak_SetParameter(espeakVOLUME, (s->volume + 1) * volumeMultiplier, 0); - espeak_SetParameter(espeakCAPITALS, 0, 0); - paused_espeak = 0; - return 0; -} - -/* Wait for up to a second before retrying an entry which could not be - * processed, so that we do not busy-loop on a persistent error. Called - * and returns with queue_guard held. Wakes up immediately if a stop is - * requested. */ -static void espeak_wait_retry(void) -{ - struct timespec timeout; - - clock_gettime(CLOCK_MONOTONIC, &timeout); - timeout.tv_sec++; - pthread_cond_timedwait(&wake_stop, &queue_guard, &timeout); -} - -/* Handle an entry which could not be processed. Called and returns - * with queue_guard held. - * Normally just back off before the retry, but watch out for a wedged - * engine: if entries keep failing while the synth callback shows no - * progress at all, restart the engine, and if restarting does not help - * either, exit so that the init system respawns us in a clean state. */ -static void espeak_handle_failure(struct synth_t *s) -{ - if (atomic_exchange(&synth_progressed, 0)) { - /* Espeak is making progress, it is merely backlogged. */ - stalled_retries = 0; - } else if (++stalled_retries >= ESPEAK_STALL_RETRIES) { - stalled_retries = 0; - if (++restart_attempts > ESPEAK_MAX_RESTARTS) { - fprintf(stderr, "espeakup: espeak keeps failing without " - "making progress and restarting it did not help, " - "aborting\n"); - /* Use _exit because exit could hang in library destructors - * while the audio device is wedged. */ - _exit(3); - } - fprintf(stderr, "espeakup: espeak has been failing without " - "making progress for %d seconds, restarting it\n", - ESPEAK_STALL_RETRIES); - /* Call into espeak with queue_guard released: these calls can - * take time, or block on a wedged audio device. If they do - * block forever, the stop-acknowledgement timeout in the - * softsynth thread is our last resort. */ - pthread_mutex_unlock(&queue_guard); - if (!paused_espeak) { - espeak_Cancel(); - espeak_Terminate(); - paused_espeak = 1; - } - reinitialize_espeak(s); - clock_gettime(CLOCK_MONOTONIC, &last_restart); - pthread_mutex_lock(&queue_guard); - return; - } - - espeak_wait_retry(); -} - -static struct espeak_entry_t *current = NULL; -static void queue_process_entry(struct synth_t *s) -{ - espeak_ERROR error = EE_OK; - char markbuff[50]; - - if (current != queue_peek(synth_queue)) { - if (current) - free_espeak_entry(current); - current = queue_peek(synth_queue); - } - pthread_mutex_unlock(&queue_guard); - - if (current->cmd != CMD_PAUSE && paused_espeak) { - if (reinitialize_espeak(s) < 0) { - /* Espeak is unavailable, so the entry cannot be processed. - * Calling espeak functions on a terminated engine would - * just fail (or worse). Leave the entry queued and retry - * after a small pause. */ - pthread_mutex_lock(&queue_guard); - espeak_handle_failure(s); - return; - } - } - - switch (current->cmd) { - case CMD_SET_FREQUENCY: - error = set_frequency(s, current->value, current->adjust); - break; - case CMD_SET_MARK: - snprintf(markbuff, sizeof(markbuff), "", - current->value); - error = espeak_Synth(markbuff, strlen(markbuff) + 1, 0, POS_CHARACTER, - 0, espeakSSML, NULL, NULL); - break; - case CMD_SET_PITCH: - error = set_pitch(s, current->value, current->adjust); - break; - case CMD_SET_RANGE: - error = set_range(s, current->value, current->adjust); - break; - case CMD_SET_PUNCTUATION: - error = set_punctuation(s, current->value, current->adjust); - break; - case CMD_SET_RATE: - error = set_rate(s, current->value, current->adjust); - break; - case CMD_SET_VOICE: - error = EE_OK; - break; - case CMD_SET_VOLUME: - error = set_volume(s, current->value, current->adjust); - break; - case CMD_SPEAK_TEXT: - s->buf = current->buf; - s->len = current->len; - error = speak_text(s); - break; - case CMD_PAUSE: - if (!paused_espeak) { - error = espeak_Cancel(); - if (error == EE_OK) - error = espeak_Terminate(); - if (error == EE_OK) - paused_espeak = 1; - } else { - error = EE_OK; - } - break; - default: - /* Uh? */ - error = EE_OK; - break; - } - - pthread_mutex_lock(&queue_guard); - if (error == EE_OK) { - /* Processed, drop it */ - struct espeak_entry_t *unqueued = queue_remove(synth_queue); - assert(unqueued == current); - free_espeak_entry(current); - current = NULL; - stalled_retries = 0; - if (restart_attempts) { - /* Forget about past restarts once the engine has been - * healthy for a while. Entries can spuriously succeed - * right after a restart while the audio output is still - * wedged (espeak's internal queue is empty again), so a - * quick success must not reset the counter. */ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - if (now.tv_sec - last_restart.tv_sec >= ESPEAK_HEALTHY_SECS) - restart_attempts = 0; - } - } else { - if (error != EE_BUFFER_FULL) - fprintf(stderr, "espeak error: %d\n", error); - /* The entry stays queued and will be retried. Give espeak a - * little break before that, whatever the error: previously only - * EE_BUFFER_FULL throttled, and any other persistent error made - * us retry the same entry in a tight loop, burning a whole CPU. */ - espeak_handle_failure(s); - } -} - -int initialize_espeak(struct synth_t *s) -{ - int rate; - - /* initialize espeak */ - rate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0); - if (rate < 0) { - fprintf(stderr, "Unable to initialize espeak.\n"); - return -1; - } - - espeak_SetSynthCallback(callback); - - /* Setup initial voice parameters */ - if (defaultVoice && defaultVoice[0]) { - set_voice(s, defaultVoice); - free(defaultVoice); - defaultVoice = NULL; - } - set_frequency(s, defaultFrequency, ADJ_SET); - set_pitch(s, defaultPitch, ADJ_SET); - set_range(s, defaultRange, ADJ_SET); - set_rate(s, defaultRate, ADJ_SET); - set_volume(s, defaultVolume, ADJ_SET); - espeak_SetParameter(espeakCAPITALS, 0, 0); - paused_espeak = 0; - return 0; -} - -/* espeak_thread is the "main" function of our secondary (queue-processing) - * thread. - * First, lock queue_guard, because it needs to be locked when we call - * pthread_cond_wait on the runner_awake condition variable. - * Next, enter an infinite loop. - * The wait call also unlocks queue_guard, so that the other thread can - * manipulate the queue. - * When runner_awake is signaled, the pthread_cond_wait call re-locks - * queue_guard, and the "queue processor" thread has access to the queue. - * While there is an entry in the queue, call queue_process_entry. - * queue_process_entry unlocks queue_guard after removing an item from the - * queue, so that the main thread doesn't have to wait for us to finish - * processing the entry. So re-lock queue_guard after each call to - * queue_process_entry. - * - * The main thread can add items to the queue in exactly two situations: - * 1. We are waiting on runner_awake, or - * 2. We are processing an entry that has just been removed from the queue. - */ -void *espeak_thread(void *arg) -{ - struct synth_t *s = (struct synth_t *) arg; - - pthread_mutex_lock(&queue_guard); - while (should_run) { - while (should_run && !queue_peek(synth_queue) && !stop_requested) - pthread_cond_wait(&runner_awake, &queue_guard); - - if (stop_requested) { - current = NULL; - /* Call into espeak with queue_guard released: espeak_Cancel - * can take time, or even block indefinitely when the audio - * output is wedged, and holding the lock here would prevent - * the other threads from ever making progress again. The - * queue cannot change concurrently: the only producer (the - * softsynth thread) is blocked waiting for stop_acknowledged - * as long as stop_requested is set. */ - pthread_mutex_unlock(&queue_guard); - stop_speech(); - pthread_mutex_lock(&queue_guard); - synth_queue_clear(); - stop_requested = 0; - pthread_cond_signal(&stop_acknowledged); - } - - while (should_run && queue_peek(synth_queue) && !stop_requested) { - queue_process_entry(s); - } - } - pthread_cond_signal(&stop_acknowledged); - pthread_mutex_unlock(&queue_guard); - return NULL; -} diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 6221208..0000000 --- a/src/meson.build +++ /dev/null @@ -1,10 +0,0 @@ -espeakup_sources = files([ - 'cli.c', - 'espeak.c', - 'espeakup.c', - 'queue.c', - 'signal.c', - 'softsynth.c', - 'stringhandling.c' -]) -espeakup_version = vcs_tag(input : 'version.h.in', output : 'version.h') diff --git a/src/version.h.in b/src/version.h.in deleted file mode 100644 index 9ba36a9..0000000 --- a/src/version.h.in +++ /dev/null @@ -1,25 +0,0 @@ -/* - * espeakup - interface which allows speakup to use espeak-ng - * - * Copyright (C) 2008 William Hubbs - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __VERSION_H -#define __VERSION_H - -#define PACKAGE_VERSION "@VCS_TAG@" - -#endif diff --git a/src/stringhandling.c b/stringhandling.c similarity index 88% rename from src/stringhandling.c rename to stringhandling.c index 096b870..8c18a39 100644 --- a/src/stringhandling.c +++ b/stringhandling.c @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2011 William Hubbs * @@ -62,17 +62,6 @@ void *reallocMem(void *p, size_t n) return s; } -char *dupeString(char *s) -{ - char *c; - - if (!(c = strdup(s))) { - fprintf(stderr, "Out of memory!\n"); - exit(1); - } - return c; -} - char *initString(int *l) { *l = 0; @@ -86,9 +75,9 @@ void stringAndString(char **s, int *l, const char *t) oldlen = *l; newlen = oldlen + strlen(t); *l = newlen; - ++newlen; // room for the 0 + ++newlen; /* room for the 0 */ x = oldlen ^ newlen; - if (x > oldlen) { // must realloc + if (x > oldlen) { /* must realloc */ newlen |= (newlen >> 1); newlen |= (newlen >> 2); newlen |= (newlen >> 4); @@ -109,7 +98,7 @@ void stringAndBytes(char **s, int *l, const char *t, int cnt) *l = newlen; ++newlen; x = oldlen ^ newlen; - if (x > oldlen) { // must realloc + if (x > oldlen) { /* must realloc */ newlen |= (newlen >> 1); newlen |= (newlen >> 2); newlen |= (newlen >> 4); diff --git a/src/stringhandling.h b/stringhandling.h similarity index 91% rename from src/stringhandling.h rename to stringhandling.h index 7f104ef..a7d7cea 100644 --- a/src/stringhandling.h +++ b/stringhandling.h @@ -1,5 +1,5 @@ /* - * espeakup - interface which allows speakup to use espeak-ng + * espeakup - interface which allows speakup to use espeak * * Copyright (C) 2011 William Hubbs * @@ -26,7 +26,6 @@ extern char *EMPTYSTRING; void *allocMem(size_t n); void *reallocMem(void *p, size_t n); -char *dupeString(char *s); char *initString(int *l); void stringAndString(char **s, int *l, const char *t); void stringAndBytes(char **s, int *l, const char *t, int cnt);