diff --git a/Mobile/NUI/TextReader/LICENSE b/Mobile/NUI/TextReader/LICENSE new file mode 100644 index 00000000..4d4d2443 --- /dev/null +++ b/Mobile/NUI/TextReader/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 Samsung + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Mobile/NUI/TextReader/README.md b/Mobile/NUI/TextReader/README.md new file mode 100644 index 00000000..a05f555c --- /dev/null +++ b/Mobile/NUI/TextReader/README.md @@ -0,0 +1,36 @@ +# TextReader +Text Reader is a sample application which demonstrates how to synthesize voice. +from text using [Tizen TTS API](https://samsung.github.io/TizenFX/stable/api/Tizen.Uix.Tts.html). + +![Main page](./Screenshots/ScreenShot-1.png) +![Main page - reading state with repeat unit](./Screenshots/ScreenShot-2.png) +![Main page - reading state with repeat all](./Screenshots/ScreenShot-3.png) + +### Verified Version +* Tizen.NET : 11.0.0.17614 +* Tizen.NET.SDK : 5.0 + +### Features +* Text divided into paragraphs +* Start/pause +* Previous/next paragraph +* Repeat unit +* Repeat all +* Reset + +### Prerequisites + +* [Visual Studio](https://www.visualstudio.com/) - Buildtool, IDE +* [Visual Studio Tools for Tizen](https://docs.tizen.org/application/vstools/install) - Visual Studio plugin for Tizen .NET application development + + +### Supported Profile +* Mobile + +### Author +* Abedalrahman Rasem (a.sheikha@samsung.com) + + + + + diff --git a/Mobile/NUI/TextReader/ScreenShots/ScreenShot-1.png b/Mobile/NUI/TextReader/ScreenShots/ScreenShot-1.png new file mode 100644 index 00000000..d4e3798a Binary files /dev/null and b/Mobile/NUI/TextReader/ScreenShots/ScreenShot-1.png differ diff --git a/Mobile/NUI/TextReader/ScreenShots/ScreenShot-2.png b/Mobile/NUI/TextReader/ScreenShots/ScreenShot-2.png new file mode 100644 index 00000000..a39cfd1c Binary files /dev/null and b/Mobile/NUI/TextReader/ScreenShots/ScreenShot-2.png differ diff --git a/Mobile/NUI/TextReader/ScreenShots/ScreenShot-3.png b/Mobile/NUI/TextReader/ScreenShots/ScreenShot-3.png new file mode 100644 index 00000000..86a04967 Binary files /dev/null and b/Mobile/NUI/TextReader/ScreenShots/ScreenShot-3.png differ diff --git a/Mobile/NUI/TextReader/TextReader/Main.cs b/Mobile/NUI/TextReader/TextReader/Main.cs new file mode 100644 index 00000000..81e60893 --- /dev/null +++ b/Mobile/NUI/TextReader/TextReader/Main.cs @@ -0,0 +1,45 @@ +using System; +using TextReader_UI.views; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; + +namespace TextReader +{ + internal class Program : NUIApplication + { + private Window window; + private Navigator navigator; + protected override void OnCreate() + { + base.OnCreate(); + Initialize(); + ContentPage mainPage = new MainPage(window.Size.Height, window.Size.Width); + navigator.Push(mainPage); + + + } + + void Initialize() + { + window = GetDefaultWindow(); + window.Title = "IMEManager"; + window.KeyEvent += OnKeyEvent; + navigator = window.GetDefaultNavigator(); + } + + public void OnKeyEvent(object sender, Window.KeyEventArgs e) + { + if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape")) + { + Exit(); + } + } + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } + } +} diff --git a/Mobile/NUI/TextReader/TextReader/Services/TextToSpeechService.cs b/Mobile/NUI/TextReader/TextReader/Services/TextToSpeechService.cs new file mode 100644 index 00000000..0a146382 --- /dev/null +++ b/Mobile/NUI/TextReader/TextReader/Services/TextToSpeechService.cs @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Linq; +using Tizen.Uix.Tts; + +namespace TextReader.TizenMobile.Services +{ + /// + /// Tizen text-to-speech service which allows to synthesize a text into speech. + /// + class TextToSpeechService + { + #region consts + + /// + /// Default voice language. + /// + private const string DEFAULT_VOICE_LANGUAGE = "en_US"; + + /// + /// Paragraphs That will be processed. + /// + private readonly string[] _paragraphs = +{ + "Welcome to Tizen .NET!", + + "Tizen .NET is an exciting new way to develop applications for the Tizen operating" + + " system, running on 50 million Samsung devices, including TVs, wearables," + + " mobile, and many other IoT devices around the world.", + + "The existing Tizen frameworks are either C-based with no advantages of a managed" + + " runtime, or HTML5-based with fewer features and lower performance than" + + " the C-based solution.", + + "With Tizen .NET, you can use the C# programming language and the Common Language" + + " Infrastructure standards and benefit from a managed runtime for faster" + + " application development, and efficient, secure code execution." + }; + + #endregion + + #region fields + + /// + /// Instance of TTS client. + /// + private readonly TtsClient _client; + + /// + /// Flag change when paragraph added. + /// + private bool _addedflag; + + /// + /// Current Index paragraph. + /// + private int _currentindex; + + /// + /// Flag for the current paragraph repeat. + /// + private bool _currentunit; + + /// + /// Flag for the all paragraph repeat. + /// + private bool _allunits; + + /// + /// Currently synthesized text. + /// + private string _text; + + /// + /// Currently used voice instance. + /// + private SupportedVoice _currentVoice; + + /// + /// Action to be called in the UI as a function when the paragraph reading starts. + /// + private Action OnStart; + + /// + /// Action to be called in the UI as a function when the paragraph reading ends. + /// + private Action OnFinish; + + #endregion + + #region properties + + /// + /// Event fired when the utterance is completed. + /// + public event EventHandler UtteranceCompleted; + + + + /// + /// Flag indicating if service is ready to use. + /// The service requires "Init" method to be called before use. + /// + public bool Ready + { + get + { + var state = _client.CurrentState; + return state != State.Created && state != State.Unavailable; + } + } + + /// + /// Currently used text. + /// If text is changed, the current utterance is stopped immediately + /// and new one starts then. + /// + public string Text + { + get { return _text; } + set + { + if (!Ready) + { + return; + } + + bool playingBeforeChange = Playing; + + _client.Stop(); + _client.AddText( + value, + _currentVoice.Language, + (int)_currentVoice.VoiceType, + _client.GetSpeedRange().Normal); + + _text = value; + + if (playingBeforeChange) + { + _client.Play(); + } + } + } + + /// + /// Flag indicating if text is read by the TTS engine. + /// + public bool Playing => _client.CurrentState == State.Playing; + + #endregion + + #region methods + + /// + /// Validation for the paragraph index. + /// + /// paragraph index. + private void Validcounter(ref int paragraphIndex) { + if (paragraphIndex >= 4) { paragraphIndex = 0; return; } + if (paragraphIndex < 0) { paragraphIndex = 3; } + } + + /// + /// Reset currentIndex and repeatType . + /// + public void Reset() + { + try + { + _currentindex = -1; + _addedflag = false; + _allunits = false; + _currentunit = false; + _client.Stop(); + } + catch (Exception e) { + Console.WriteLine(e.Message); + } + } + + /// + /// Setting current paragraph index. + /// + /// paragraph current index. + public void SetCurrentUnit(int currentUnit) + { + _currentindex = currentUnit; + _addedflag = false; + + if (Playing) + { + _client.Stop(); + _client.AddText(_paragraphs[_currentindex], + _currentVoice.Language, + (int)_currentVoice.VoiceType, + _client.GetSpeedRange().Normal); + _addedflag = true; + _client.Play(); + } + } + + /// + /// Setting repeat type. + /// + /// repeat type. + public void SetRepeat(int repeatType) { + try + { + if (repeatType == 3) + { + _currentindex++; + Validcounter(ref _currentindex); + _addedflag = false; + + if (Playing) + { + _client.Stop(); + _client.AddText(_paragraphs[_currentindex], + _currentVoice.Language, + (int)_currentVoice.VoiceType, + _client.GetSpeedRange().Normal); + _addedflag = true; + _client.Play(); + OnStart(_currentindex); + } + } + else if (repeatType == 4) + { + _currentindex--; + Validcounter(ref _currentindex); + _addedflag = false; + + if (Playing) + { + _client.Stop(); + _client.AddText(_paragraphs[_currentindex], + _currentVoice.Language, + (int)_currentVoice.VoiceType, + _client.GetSpeedRange().Normal); + _client.Play(); + _addedflag = true; + OnStart(_currentindex); + } + } + else if (repeatType == 1) + { + _allunits = true; + } + else if (repeatType == 2) + { + _currentunit = true; + } + else if (repeatType == -2) + { + _currentunit = false; + } + else if (repeatType == -1) { + _allunits = false; + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + /// + /// The service constructor. + /// + public TextToSpeechService(Action OnStart, Action OnFinish) + { + this.OnStart = OnStart; + this.OnFinish = OnFinish; + _client = new TtsClient(); + _client.UtteranceCompleted += ClientOnUtteranceCompleted; + _client.UtteranceStarted += Client_UtteranceStarted; + _currentindex = -1; + _currentunit = false; + _allunits = false; + _addedflag = false; + } + + private void Client_UtteranceStarted(object sender, UtteranceEventArgs e) + { + OnStart(_currentindex); + } + + /// + /// Handles utterance completed event on TTS client. + /// Invokes UtteranceCompleted event. + /// + /// Event sender. + /// Event arguments. + private void ClientOnUtteranceCompleted(object sender, UtteranceEventArgs utteranceEventArgs) + { + UtteranceCompleted?.Invoke(this, new EventArgs()); + try + { + _currentindex++; + _addedflag = false; + + if (_currentunit) + { + _currentindex--; + } + else if ((_currentindex > 3 || _currentindex < 0) && _allunits) { _currentindex = 0; } + + if (_currentindex <= 3 && _currentindex >= 0) + { + _client.AddText(_paragraphs[_currentindex], + _currentVoice.Language, + (int)_currentVoice.VoiceType, + _client.GetSpeedRange().Normal); + _addedflag = true; + } + OnFinish(_currentindex); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + + } + + /// + /// Initializes the service. + /// Service can be used when the "Ready" property returns "true" value. + /// + public void Init() + { + if (Ready) + { + return; + } + + if (_client.DefaultVoice.Language == DEFAULT_VOICE_LANGUAGE) + { + _currentVoice = _client.DefaultVoice; + } + else + { + _currentVoice = _client.GetSupportedVoices(). + FirstOrDefault(voice => voice.Language == DEFAULT_VOICE_LANGUAGE) ?? + _client.DefaultVoice; + } + + _client.Prepare(); + } + + /// + /// Starts or resumes the current utterance. + /// + + public void Play() + { + if(_currentindex != -1 &&!_addedflag) + { + Validcounter(ref _currentindex); + _client.AddText( _paragraphs[_currentindex], + _currentVoice.Language, + (int)_currentVoice.VoiceType, + _client.GetSpeedRange().Normal); + _addedflag = true; + } + if(!Ready) + { + return; + } + + try + { + _client.Play(); + } + catch (Exception e) { Console.WriteLine(e.Message); } + } + + /// + /// Getting the current paragraph index. + /// + public int GetCurrentParagraph() { return _currentindex; } + + /// + /// Pauses the current utterance. + /// + public void Pause() + { + if (!Ready) + { + return; + } + if (Playing) + _client.Pause(); + + } + + /// + /// Stops and clears the current utterance. + /// + public void Stop() + { + if (!Ready) + { + return; + } + + _client.Stop(); + } + + /// + /// Dispose and kill object. + /// + public void Dispose() + { + try + { + _client.Dispose(); + } + + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + #endregion + } +} diff --git a/Mobile/NUI/TextReader/TextReader/TextReader.csproj b/Mobile/NUI/TextReader/TextReader/TextReader.csproj new file mode 100644 index 00000000..58b952f2 --- /dev/null +++ b/Mobile/NUI/TextReader/TextReader/TextReader.csproj @@ -0,0 +1,6 @@ + + + net6.0-tizen + Exe + + \ No newline at end of file diff --git a/Mobile/NUI/TextReader/TextReader/TextReader.sln b/Mobile/NUI/TextReader/TextReader/TextReader.sln new file mode 100644 index 00000000..40958f22 --- /dev/null +++ b/Mobile/NUI/TextReader/TextReader/TextReader.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33122.133 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TextReader", "TextReader.csproj", "{724EB20B-7DE0-4D57-BFB1-87D36B2908E0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {724EB20B-7DE0-4D57-BFB1-87D36B2908E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {724EB20B-7DE0-4D57-BFB1-87D36B2908E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {724EB20B-7DE0-4D57-BFB1-87D36B2908E0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {724EB20B-7DE0-4D57-BFB1-87D36B2908E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {724EB20B-7DE0-4D57-BFB1-87D36B2908E0}.Release|Any CPU.Build.0 = Release|Any CPU + {724EB20B-7DE0-4D57-BFB1-87D36B2908E0}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F9255EB2-7F6C-482C-8415-F9484DFDA9DC} + EndGlobalSection +EndGlobal diff --git a/Mobile/NUI/TextReader/TextReader/res/images/active_unit_line.png b/Mobile/NUI/TextReader/TextReader/res/images/active_unit_line.png new file mode 100644 index 00000000..7fe02ef4 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/active_unit_line.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/back.png b/Mobile/NUI/TextReader/TextReader/res/images/back.png new file mode 100644 index 00000000..9c62950c Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/back.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/back_hover.png b/Mobile/NUI/TextReader/TextReader/res/images/back_hover.png new file mode 100644 index 00000000..f780c85e Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/back_hover.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/bg.png b/Mobile/NUI/TextReader/TextReader/res/images/bg.png new file mode 100644 index 00000000..5d74b043 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/bg.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/bg_1.png b/Mobile/NUI/TextReader/TextReader/res/images/bg_1.png new file mode 100644 index 00000000..875b1f65 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/bg_1.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/forward.png b/Mobile/NUI/TextReader/TextReader/res/images/forward.png new file mode 100644 index 00000000..ab76dac0 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/forward.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/forward_hover.png b/Mobile/NUI/TextReader/TextReader/res/images/forward_hover.png new file mode 100644 index 00000000..97f80c07 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/forward_hover.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/pause.png b/Mobile/NUI/TextReader/TextReader/res/images/pause.png new file mode 100644 index 00000000..1e1d9bf4 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/pause.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/pause_hover.png b/Mobile/NUI/TextReader/TextReader/res/images/pause_hover.png new file mode 100644 index 00000000..f7ce55fc Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/pause_hover.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/play.png b/Mobile/NUI/TextReader/TextReader/res/images/play.png new file mode 100644 index 00000000..ed26223b Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/play.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/play_hover.png b/Mobile/NUI/TextReader/TextReader/res/images/play_hover.png new file mode 100644 index 00000000..625ece94 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/play_hover.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/repeat_all.png b/Mobile/NUI/TextReader/TextReader/res/images/repeat_all.png new file mode 100644 index 00000000..9bee8278 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/repeat_all.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/repeat_all_hover.png b/Mobile/NUI/TextReader/TextReader/res/images/repeat_all_hover.png new file mode 100644 index 00000000..8cf28e70 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/repeat_all_hover.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/repeat_unit.png b/Mobile/NUI/TextReader/TextReader/res/images/repeat_unit.png new file mode 100644 index 00000000..8f21a8bc Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/repeat_unit.png differ diff --git a/Mobile/NUI/TextReader/TextReader/res/images/repeat_unit_hover.png b/Mobile/NUI/TextReader/TextReader/res/images/repeat_unit_hover.png new file mode 100644 index 00000000..519e0200 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/res/images/repeat_unit_hover.png differ diff --git a/Mobile/NUI/TextReader/TextReader/shared/res/TextReader.png b/Mobile/NUI/TextReader/TextReader/shared/res/TextReader.png new file mode 100644 index 00000000..9f3cb986 Binary files /dev/null and b/Mobile/NUI/TextReader/TextReader/shared/res/TextReader.png differ diff --git a/Mobile/NUI/TextReader/TextReader/tizen-manifest.xml b/Mobile/NUI/TextReader/TextReader/tizen-manifest.xml new file mode 100644 index 00000000..041cb106 --- /dev/null +++ b/Mobile/NUI/TextReader/TextReader/tizen-manifest.xml @@ -0,0 +1,9 @@ + + + + + + TextReader.png + + + diff --git a/Mobile/NUI/TextReader/TextReader/views/MainPage.cs b/Mobile/NUI/TextReader/TextReader/views/MainPage.cs new file mode 100644 index 00000000..c5385e12 --- /dev/null +++ b/Mobile/NUI/TextReader/TextReader/views/MainPage.cs @@ -0,0 +1,613 @@ +using System; +using Tizen.Applications; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Components; +using TextReader.TizenMobile.Services; + +namespace TextReader_UI.views +{ + class MainPage : ContentPage + { + //Flags for play , repeat , repeat all status. + bool playButtonFlag = false; + bool repeatAllFlag = false; + bool repeatAllUnitFlag = false; + + //Getting the path for images. + public string directory = Application.Current.DirectoryInfo.Resource; + + //Storing the selected paragraph id. + public int selectedParagraphId = -1; + + //Creating object of the TextToSpeechService Service. + public TextToSpeechService textToSpeechService; + + //Setting consts. + public const string backgroundColor = "#00a9bf"; + public const string resetColor = "#99CAD2"; + + public int playCounter = 0; + + private readonly string[] _paragraphs = + { + "Welcome to Tizen .NET!", + + "Tizen .NET is an exciting new way to develop applications for the Tizen operating" + + " system, running on 50 million Samsung devices, including TVs, wearables," + + " mobile, and many other IoT devices around the world.", + + "The existing Tizen frameworks are either C-based with no advantages of a managed" + + " runtime, or HTML5-based with fewer features and lower performance than" + + " the C-based solution.", + + "With Tizen .NET, you can use the C# programming language and the Common Language" + + " Infrastructure standards and benefit from a managed runtime for faster" + + " application development, and efficient, secure code execution." + }; + + //Creating TextLabel array for paragraphs. + private TextLabel [] paragraphLabel =new TextLabel [4]; + + + //Play button for controlling the Service . + private Button playButton; + + //Creating Images to show when paragraph is selected or being played. + ImageView[] activeParagrphUnitLineImg = new ImageView[4]; + + //Styling the paragraph when the its finished. + private Action FinishEffect; + + //Styling the paragraph when the its started. + + private Action StartEffect; + public MainPage(float height, float width){ + + StartEffect = delegate(int currentParagraph) + { + for(int i = 0; i < 4; i++){ + if(i == currentParagraph){ + paragraphLabel[i].TextColor = new Color(backgroundColor); + activeParagrphUnitLineImg[i].Show(); + } + else + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + } + }; + + FinishEffect = delegate(int currentParagraph) + { + for(int i = 0; i <= 4; i++) + { + if(currentParagraph == 4 && i==4) + { + paragraphLabel[i-1].TextColor = new Color(0, 0, 0, 0.6f); + playButton.BackgroundImage = Application.Current.DirectoryInfo.Resource + "images/play.png"; + activeParagrphUnitLineImg[i-1].Hide(); + textToSpeechService.Stop(); + selectedParagraphId = -1; + playButtonFlag = false; + return; + } + else if(i == currentParagraph) + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + } + selectedParagraphId = -1; + }; + + textToSpeechService = new TextToSpeechService(OnStart: StartEffect, OnFinish : FinishEffect); + + //Initializing the TTS object. + textToSpeechService.Init(); + + //Styling the text for the appbar. + var mainAppBarTextStyle = new PropertyMap(); + mainAppBarTextStyle.Add("slant", new PropertyValue(FontSlantType.Normal.ToString())); + mainAppBarTextStyle.Add("width", new PropertyValue(FontWidthType.Expanded.ToString())); + mainAppBarTextStyle.Add("weight", new PropertyValue(FontWeightType.DemiBold.ToString())); + + //Button view to hold the buttons horizontally + View buttonView = new View() + { + SizeWidth = width, + SizeHeight = height * 0.15f, + BackgroundColor = Color.Transparent, + Layout = new LinearLayout() + { + LinearOrientation = LinearLayout.Orientation.Horizontal, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + CellPadding = new Size2D(20, 10), + }, + + }; + + //Create button + playButton = new Button() + { + SizeWidth = 125, + SizeHeight = 125, + BackgroundImage = directory + "/images/play.png", + }; + + //Cancel button + Button backwardButton = new Button() + { + SizeWidth = 125, + SizeHeight = 125, + BackgroundImage = directory + "/images/back.png", + }; + + //Stop button + Button forwardButton = new Button() + { + SizeWidth = 125, + SizeHeight = 125, + BackgroundImage = directory + "/images/forward.png", + }; + + //RpeatAll button + Button repeatAll = new Button() + { + SizeWidth = 125, + SizeHeight = 125, + BackgroundImage = directory + "/images/repeat_all.png", + }; + + //RpeatCurrentUnit button + Button repeatAllUnit = new Button() + { + SizeWidth = 125, + SizeHeight = 125, + BackgroundImage = directory + "/images/repeat_unit.png", + }; + + //Accept reset button + Button okButton = new Button() + { + Text= "OK", + }; + + //Deny reset button + Button cancelButton = new Button() + { + Text= "Cancel", + }; + + //Reset button + Button reseButton = new Button() + { + SizeWidth = width * 0.3f, + BackgroundColor = Color.Transparent, + PointSize = 8, + TextColor = new Color(resetColor), + Text = "RESET", + IsEnabled=false, + }; + + //Creating the AppBar + AppBar appBar = new AppBar() + { + SizeHeight = height*0.1f, + SizeWidth = width, + BackgroundColor = Color.Transparent, + ActionContent = reseButton, + NavigationContent =new View() { SizeWidth = width * 0.3f}, + Margin = new Extents(200,0,0,0), + TitleContent = new TextLabel() + { + BackgroundColor = Color.Transparent, + SizeWidth = width * 0.4f, + Text = "Text Reader", + PointSize = 10, + TextColor = Color.White, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + FontStyle = mainAppBarTextStyle, + WidthSpecification = LayoutParamPolicies.MatchParent, + }, + }; + + //Creating mainView + View mainView = new View() + { + LayoutDirection = ViewLayoutDirectionType.LTR, + SizeHeight = height - (height / 12), + SizeWidth = width, + Layout = new LinearLayout() + { + LinearOrientation = LinearLayout.Orientation.Vertical, + }, + }; + + //Text view to hold the paragraph text + View textView = new View() + { + SizeWidth = width, + SizeHeight = height * 0.75f, + BackgroundColor = Color.White, + Layout = new LinearLayout() + { + LinearOrientation = LinearLayout.Orientation.Vertical, + }, + Padding = new Extents(25, 25, 75, 0), + }; + + //Creating TextLabel for paragraph. + for (int i = 0; i < 4; i++) + { + activeParagrphUnitLineImg[i] = new ImageView(); + activeParagrphUnitLineImg[i].Hide(); + activeParagrphUnitLineImg[i].SetImage(directory + "/images/active_unit_line.png"); + paragraphLabel[i]= new TextLabel() + { + SizeWidth = width, + SizeHeight= (float)(height *0.1), + PointSize = 6, + TextColor = new Color(0, 0, 0, 0.6f), + WidthSpecification = LayoutParamPolicies.MatchParent, + BackgroundColor = Color.Transparent, + MultiLine = true, + }; + } + + //Setting height for the first paragraph. + paragraphLabel[0].SizeHeight = 50f; + + //Paragraph and Button Effects. + paragraphLabel[0].TouchEvent += (object sender, TouchEventArgs e) => + { + if ((e.Touch.GetState(0) == PointStateType.Started) && selectedParagraphId != 0 && (textToSpeechService.GetCurrentParagraph() != 0)) + { + for (int i = 0; i < 4; i++) + { + if (i == 0) + { + paragraphLabel[i].TextColor = new Color(backgroundColor); + textToSpeechService.SetCurrentUnit(i); + activeParagrphUnitLineImg[i].Show(); + } + else + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + } + selectedParagraphId = 0; + } + return true; + }; + + paragraphLabel[1].TouchEvent += (object sender, TouchEventArgs e) => + { + if ((e.Touch.GetState(0) == PointStateType.Started) && selectedParagraphId != 1 && (textToSpeechService.GetCurrentParagraph() != 1)) + { + for (int i = 0; i < 4; i++) + { + if (i == 1) + { + paragraphLabel[i].TextColor = new Color(backgroundColor); + textToSpeechService.SetCurrentUnit(i); + activeParagrphUnitLineImg[i].Show(); + } + else + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + } + selectedParagraphId = 1; + } + return true; + }; + + paragraphLabel[2].TouchEvent += (object sender, TouchEventArgs e) => + { + if ((e.Touch.GetState(0) == PointStateType.Started) && (selectedParagraphId != 2) && (textToSpeechService.GetCurrentParagraph()!=2)) + { + for (int i = 0; i < 4; i++) + { + if (i == 2) + { + paragraphLabel[i].TextColor = new Color(backgroundColor); + textToSpeechService.SetCurrentUnit(i); + activeParagrphUnitLineImg[i].Show(); + } + else + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + } + selectedParagraphId = 2; + } + return true; + }; + + paragraphLabel[3].TouchEvent += (object sender, TouchEventArgs e) => + { + if ((e.Touch.GetState(0) == PointStateType.Started)&&selectedParagraphId!=3 ) + { + for (int i = 0; i < 4; i++) + { + if (i == 3) + { + paragraphLabel[i].TextColor = new Color(backgroundColor); + textToSpeechService.SetCurrentUnit(i); + activeParagrphUnitLineImg[i].Show(); + } + else + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + } + selectedParagraphId = 3; + } + return true; + }; + + playButtonFlag = false; + + playButton.TouchEvent += (object sender, TouchEventArgs e) => + { + reseButton.IsEnabled = true; + reseButton.TextColor = Color.White; + if (e.Touch.GetState(0) == PointStateType.Started) + { + //Change icon to pressed + if (!playButtonFlag) + { + playButton.BackgroundImage = directory + "images/play_hover.png"; + } + else + { + playButton.BackgroundImage = directory + "images/pause_hover.png"; + } + } + if (e.Touch.GetState(0) == PointStateType.Leave) + { + //Return the default icon + if (!playButtonFlag) + { + playButtonFlag = false; + playButton.BackgroundImage = directory + "images/play.png"; + playCounter++; + textToSpeechService.Pause(); + } + else + { + playButtonFlag = true; + playButton.BackgroundImage = directory + "images/pause.png"; + + if (textToSpeechService.GetCurrentParagraph() == -1) + { + textToSpeechService.SetCurrentUnit(0); + textToSpeechService.Play(); + } + else + { + textToSpeechService.Play(); + } + } + } + if (e.Touch.GetState(0) == PointStateType.Finished) + { + //Return the default icon + if (!playButtonFlag) { + playButtonFlag = true; + playButton.BackgroundImage = directory + "images/pause.png"; + + if (textToSpeechService.GetCurrentParagraph() == -1) + { + textToSpeechService.SetCurrentUnit(0); + textToSpeechService.Play(); + } + else + { + textToSpeechService.Play(); + } + } + else + { + playButtonFlag = false; + playButton.BackgroundImage = directory + "images/play.png"; + playCounter++; + textToSpeechService.Pause(); + } + } + return true; + }; + + backwardButton.TouchEvent += (object sender, TouchEventArgs e) => + { + if (e.Touch.GetState(0) == PointStateType.Started) + { + //Change icon to pressed + backwardButton.BackgroundImage = directory + "images/back_hover.png"; + } + if (e.Touch.GetState(0) == PointStateType.Leave) + { //Return the default icon + backwardButton.BackgroundImage = directory + "images/back.png"; + } + if (e.Touch.GetState(0) == PointStateType.Finished) + { //Return the default icon + backwardButton.BackgroundImage = directory + "images/back.png"; + textToSpeechService.SetRepeat(4); + } + return true; + }; + + forwardButton.TouchEvent += (object sender, TouchEventArgs e) => + { + if (e.Touch.GetState(0) == PointStateType.Started) + { + //Change icon to pressed + forwardButton.BackgroundImage = directory + "images/forward_hover.png"; + } + + if (e.Touch.GetState(0) == PointStateType.Finished) + { + //Return the default icon + forwardButton.BackgroundImage = directory + "images/forward.png"; + textToSpeechService.SetRepeat(3); + } + return true; + }; + + repeatAll.TouchEvent += (object sender, TouchEventArgs e) => + { + if (e.Touch.GetState(0) == PointStateType.Started) + { + //Change icon to pressed + repeatAll.BackgroundImage = directory + "images/repeat_all_hover.png"; + } + + if (e.Touch.GetState(0) == PointStateType.Finished) + { + if (repeatAllFlag) + { + repeatAllFlag = false; + repeatAll.BackgroundImage = directory + "images/repeat_all.png"; + textToSpeechService.SetRepeat(-1); + } + else + { + repeatAllFlag = true; + repeatAll.BackgroundImage = directory + "images/repeat_all_hover.png"; + textToSpeechService.SetRepeat(1); + } + } + return true; + }; + + reseButton.IsEnabled = false; + reseButton.TextColor = new Color(resetColor); + + reseButton.Clicked += (sender, e) => + { + int counter = 0; + bool playingFlag = false; + if (textToSpeechService.Playing) + { + textToSpeechService.Pause(); + playButton.BackgroundImage = directory + "images/play.png"; + playingFlag = true; + } + + DialogPage.ShowAlertDialog("Reset Confirmation", " Are you sure you want to reset this app to default screen?", cancelButton, okButton); + + cancelButton.Clicked += (o, e) => + { + if (counter == 0) + { + counter++; + try + { + if (!textToSpeechService.Playing && playingFlag) + { playButton.BackgroundImage = directory + "images/pause.png"; + playingFlag = false; + textToSpeechService.Play(); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + playButton.BackgroundImage = directory + "images/play.png"; + textToSpeechService.Pause(); + } + Navigator.Pop(); + } + }; + + okButton.Clicked += (o, e) => + { + for (int i = 0; i < 4; i++) + { + paragraphLabel[i].TextColor = new Color(0, 0, 0, 0.6f); + activeParagrphUnitLineImg[i].Hide(); + } + + textToSpeechService.Reset(); + selectedParagraphId = -1; + playButtonFlag = false; + repeatAllFlag = false; + repeatAllUnitFlag = false; + reseButton.IsEnabled = false; + reseButton.TextColor = new Color(resetColor); + repeatAll.BackgroundImage = directory + "images/repeat_all.png"; + backwardButton.BackgroundImage = directory + "images/back.png"; + forwardButton.BackgroundImage = directory + "images/forward.png"; + repeatAllUnitFlag = false; repeatAllUnit.BackgroundImage = directory + "images/repeat_unit.png"; + if (counter == 0) + { + counter++; Navigator.Pop(); + } + }; + + + }; + + repeatAllUnit.TouchEvent += (object sender, TouchEventArgs e) => + { + if (e.Touch.GetState(0) == PointStateType.Started) + { + //Change icon to pressed + repeatAllUnit.BackgroundImage = directory + "images/repeat_unit_hover.png"; + } + + if (e.Touch.GetState(0) == PointStateType.Finished) + { + //Return the default icon + if (repeatAllUnitFlag) + { + repeatAllUnitFlag = false; repeatAllUnit.BackgroundImage = directory + "images/repeat_unit.png"; + textToSpeechService.SetRepeat(-2); + } + else + { + repeatAllUnit.BackgroundImage = directory + "images/repeat_unit_hover.png"; + repeatAllUnitFlag = true; + textToSpeechService.SetRepeat(2); + } + } + return true; + }; + + //Setting paragraph in textlabel and adding them to the textview. + for (int i = 0; i < 4; i++) + { + paragraphLabel[i].Text += _paragraphs[i]; + textView.Add(paragraphLabel[i]); + textView.Add(activeParagrphUnitLineImg[i]); + } + + //Add buttons to button view + buttonView.Add(repeatAllUnit); + buttonView.Add(backwardButton); + buttonView.Add(playButton); + buttonView.Add(forwardButton); + buttonView.Add(repeatAll); + + //Add views to the main view + mainView.Add(textView); + mainView.Add(buttonView); + + //Adding Components to the page + AppBar = appBar; + Content = mainView; + BackgroundColor = new Color(backgroundColor); + + } + ~MainPage() { + textToSpeechService.Dispose(); + } + } +}