Permalink
Browse files

use acapela for tts and introduce different voice providers

  • Loading branch information...
youribonnaffe committed Oct 9, 2011
1 parent d8ba2fa commit 76c36733e9b05408a4d2b8bc684bdd372abe8511
View
@@ -5,6 +5,7 @@ apply plugin: 'groovy'
apply plugin: 'gae'
apply plugin: 'gaelyk'
apply plugin: 'eclipse'
+apply plugin: 'idea'
def compatibilityVersion = 1.5
sourceCompatibility = compatibilityVersion
@@ -48,17 +49,18 @@ dependencies {
groovy 'org.codehaus.groovy:groovy-all:1.8.1'
compile "com.google.appengine:appengine-api-1.0-sdk:$gaeVersion",
"com.google.appengine:appengine-api-labs:$gaeVersion",
- 'glaforge:gaelyk:1.0'
+ 'glaforge:gaelyk:1.0',
+ 'net.sourceforge.htmlcleaner:htmlcleaner:2.2'
testCompile 'org.spockframework:spock-core:0.5-groovy-1.8', {
exclude group: 'org.codehaus.groovy', name: 'groovy-all'
}
testCompile 'marcoVermeulen:gaelyk-spock:0.1',
- "com.google.appengine:appengine-api-stubs:$gaeVersion",
- "com.google.appengine:appengine-testing:$gaeVersion",
- 'javax.servlet:servlet-api:2.5',
- 'cglib:cglib-nodep:2.2',
- 'org.objenesis:objenesis:1.2'
+ "com.google.appengine:appengine-api-stubs:$gaeVersion",
+ "com.google.appengine:appengine-testing:$gaeVersion",
+ 'javax.servlet:servlet-api:2.5',
+ 'cglib:cglib-nodep:2.2',
+ 'org.objenesis:objenesis:1.2'
gaeSdk "com.google.appengine:appengine-java-sdk:$gaeVersion"
}
@@ -70,7 +72,7 @@ gae {
}
clean.doLast {
- delete sourceSets*.classesDir
+ delete sourceSets*.classesDir
}
task copyRuntimeLibraries {
@@ -98,15 +100,11 @@ eclipseProject {
eclipseClasspath {
withXml { xml ->
xml.asNode().classpathentry.find { it.@kind == 'output' && it.@path == 'bin' }.@path = 'war/WEB-INF/classes'
- xml.asNode().appendNode('classpathentry', [kind: 'con', path: 'com.google.appengine.eclipse.core.GAE_CONTAINER'])
- .appendNode('attributes')
- .appendNode('attribute', [name: 'org.eclipse.jst.component.nondependency', value: '/war/WEB-INF/lib'])
- xml.asNode().appendNode('classpathentry', [exported: 'true', kind: 'con', path: 'GROOVY_SUPPORT'])
- .appendNode('attributes')
- .appendNode('attribute', [name: 'org.eclipse.jst.component.nondependency', value: '/war/WEB-INF/lib'])
+ xml.asNode().appendNode('classpathentry', [kind: 'con', path: 'com.google.appengine.eclipse.core.GAE_CONTAINER']).appendNode('attributes').appendNode('attribute', [name: 'org.eclipse.jst.component.nondependency', value: '/war/WEB-INF/lib'])
+ xml.asNode().appendNode('classpathentry', [exported: 'true', kind: 'con', path: 'GROOVY_SUPPORT']).appendNode('attributes').appendNode('attribute', [name: 'org.eclipse.jst.component.nondependency', value: '/war/WEB-INF/lib'])
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.0-milestone-4'
-}
+}
@@ -0,0 +1,45 @@
+package com.appspot.nabaztag
+
+import org.htmlcleaner.HtmlCleaner
+import org.htmlcleaner.SimpleXmlSerializer
+
+class Ginko {
+
+ public static String readTimeTable(String stop) {
+ String htmlTimeTable = new URL("http://www.ginkotempo.com/TempoMobile/tempoMobile.do"
+ + "?choix_station=${stop}&methode=afficheStation").text
+
+ HtmlCleaner cleaner = new HtmlCleaner();
+ def node = cleaner.clean(htmlTimeTable)
+ // Convert from HTML to XML
+ def props = cleaner.getProperties()
+ def serializer = new SimpleXmlSerializer(props)
+ def xml = serializer.getXmlAsString(node)
+
+ // Parse the XML into a document we can work with
+ def page = new XmlSlurper(false, false).parseText(xml)
+
+ def timeTable = "Station ${stop} "
+ page.body.depthFirst().
+ grep { it.name() == "tr"}.
+ grep { it.name() == "tr"}.
+ each {
+ def next = textFromFirstChild(it.td[1].a)
+ def nextNext = textFromFirstChild(it.td[2].a)
+ if (next && nextNext) {
+ timeTable += " " + it.td[0].div[0].text() + " " + it.td[0].div[1].text()
+ timeTable += " " + next
+ timeTable += " " + nextNext
+ }
+ }
+ return timeTable.replaceAll("min", "minutes")
+ }
+
+ private static String textFromFirstChild(def parent) {
+ String all = parent.text()
+ StringBuilder subtract = new StringBuilder()
+ parent.children().each { subtract.append(it.text()) }
+ return all.substring(0, all.size() - subtract.toString().size())
+ }
+
+}
@@ -1,9 +1,5 @@
package com.appspot.nabaztag
-import com.appspot.nabaztag.AmbientBlock
-import com.appspot.nabaztag.Packet
-import com.appspot.nabaztag.PingIntervalBlock
-
class Mem {
static def lastMsg = -1
@@ -1,29 +1,39 @@
package com.appspot.nabaztag
import javax.servlet.http.HttpServletResponse
+import com.appspot.nabaztag.tts.VoiceProvider
+import com.appspot.nabaztag.tts.AcapelaVoiceProvider
class RabbitCommand {
- public static byte[] say(String text){
- def message = new MessageBlock(139)
- message.addPlayStreamCommand("http://translate.google.com/translate_tts?tl=fr&q="+URLEncoder.encode(text,"UTF-8"))
- return buildPacket(message)
+ private static final int MESSAGE_ID = 139
+
+ static VoiceProvider voiceProvider = new AcapelaVoiceProvider()
+
+ public static byte[] say(String text) {
+ def message = new MessageBlock(MESSAGE_ID)
+
+ voiceProvider.convertTextToMP3(text).each{
+ message.addPlayStreamCommand(it)
+ }
+
+ return buildPacket(message)
}
- public static byte[] play(String url){
- def message = new MessageBlock(139)
- message.addPlayStreamCommand(url)
- return buildPacket(message)
+ public static byte[] play(String url) {
+ def message = new MessageBlock(MESSAGE_ID)
+ message.addPlayStreamCommand(url)
+ return buildPacket(message)
}
- public static void sendPacket(byte[] packet, HttpServletResponse response){
- response.contentLength = packet.length
- response.getOutputStream().write packet
+ public static void sendPacket(byte[] packet, HttpServletResponse response) {
+ response.contentLength = packet.length
+ response.getOutputStream().write packet
}
- private static buildPacket(MessageBlock message) {
- def packet = new Packet()
- packet.addBlock(message)
- return packet.generatePacket()
+ private static buildPacket(MessageBlock... messages) {
+ def packet = new Packet()
+ messages.each { packet.addBlock(it) }
+ return packet.generatePacket()
}
}
@@ -8,11 +8,11 @@ enum RfidAction {
private final String label;
- public RfidAction(String label){
- this.label = label
+ public RfidAction(String label) {
+ this.label = label
}
- public String label(){
- return label
+ public String label() {
+ return label
}
}
@@ -0,0 +1,28 @@
+package com.appspot.nabaztag.tts
+
+class AcapelaVoiceProvider implements VoiceProvider {
+
+ List<String> convertTextToMP3(String text) {
+ def url = "http://vaassl3.acapela-group.com/Services/Synthesizer"
+ HttpURLConnection connection = new URL(url).openConnection()
+ connection.setRequestProperty "Host", "vaassl3.acapela-group.com"
+ connection.setRequestProperty "Referer", "http://www.acapela-group.com/Flash/Demo_Web_AS3/demo_web.swf?path=http://vaas.acapela-group.com/Services/DemoWeb/&lang=EN"
+ connection.setRequestProperty "Content-type", "application/x-www-form-urlencoded"
+ connection.setRequestProperty "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ connection.setRequestProperty "Accept-Language", "fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3"
+ connection.setRequestProperty "Accept-Encoding", "gzip,deflate"
+ connection.setRequestProperty "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
+ connection.setRequestProperty "Keep-Alive", "300"
+ connection.setRequestProperty "Connection", "keep-alive"
+ connection.setRequestProperty "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1"
+
+ connection.setRequestMethod("POST")
+ connection.setDoOutput(true)
+
+ OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
+ writer.write("cl%5Fenv=FLASH%5FAS%5F3%2E0&req%5Fsnd%5Fkbps=EXT%5FCBR%5F128&req%5Fasw%5Ftype=INFO&cl%5Fvers=1%2D30&req%5Fsnd%5Ftype=&cl%5Flogin=demo%5Fweb&cl%5Fapp=&req%5Fvoice=julie22k&cl%5Fpwd=demo%5Fweb&prot%5Fvers=2&req%5Ftext=" + URLEncoder.encode(text, "UTF-8"));
+ writer.close();
+
+ return [connection.getInputStream().text.tokenize("&").find({ it =~ "snd_url"}).minus("snd_url=")]
+ }
+}
@@ -0,0 +1,24 @@
+package com.appspot.nabaztag.tts
+
+class GoogleVoiceProvider implements VoiceProvider {
+
+ List<String> convertTextToMP3(String text) {
+
+ def encodedText = text
+ def listOfStrings = new LinkedList<String>()
+ def size = 0
+ encodedText.split().each {
+
+ if (size + it.length() < 80) {
+ size += it.length()
+ def current = listOfStrings.poll()
+ listOfStrings.addFirst((current ? current : "") + " " + it)
+ } else {
+ listOfStrings.addFirst(it)
+ size = it.length()
+ }
+ }
+
+ return listOfStrings.reverse().collect { "http://translate.google.com/translate_tts?ie=UTF-8&tl=fr&q=" + URLEncoder.encode(it, "UTF-8") }
+ }
+}
@@ -0,0 +1,5 @@
+package com.appspot.nabaztag.tts
+
+interface VoiceProvider {
+ List<String> convertTextToMP3(String text);
+}
@@ -0,0 +1,18 @@
+package com.appspot.nabaztag
+
+import org.junit.Test
+import static org.hamcrest.CoreMatchers.containsString
+import static org.hamcrest.CoreMatchers.not
+import static org.junit.Assert.assertFalse
+import static org.junit.Assert.assertThat
+
+public class GinkoTest {
+
+ @Test
+ public void testTimeTableContent() {
+ String timeTable = Ginko.readTimeTable("CANOT")
+ assertFalse timeTable.isEmpty()
+ assertThat timeTable, containsString("minutes")
+ assertThat timeTable, not(containsString("min "))
+ }
+}
@@ -0,0 +1,20 @@
+package com.appspot.nabaztag;
+
+import com.appspot.nabaztag.tts.VoiceProvider
+import org.junit.Test
+import static org.junit.Assert.assertNotNull
+
+class RabbitCommandTest {
+
+ @Test
+ public void testSayText() {
+ RabbitCommand.voiceProvider = new VoiceProvider() {
+ List<String> convertTextToMP3(String text) {
+ return ["test"]
+ }
+ }
+ def packet = RabbitCommand.say "hello"
+ assertNotNull packet
+ }
+
+}
@@ -1,4 +1,5 @@
package vl
+
import com.google.appengine.api.utils.SystemProperty
log.info "bootcode"
@@ -8,33 +9,33 @@ def bootcodeAsBytes = bootcode.bytes
response.contentLength = bootcodeAsBytes.length
if (app.env.name == SystemProperty.Environment.Value.Production) {
- sout.write bootcodeAsBytes
+ sout.write bootcodeAsBytes
} else {
- sendBootCodeSlowly(bootcode)
+ sendBootCodeSlowly(bootcode)
}
response.status = 200
private sendBootCodeSlowly(bootcode) {
- def fin = bootcode.newInputStream()
- while (true) {
- int available = fin.available();
- if (available > 0) {
- int bufferSize = available;
- int BUFFER_SIZE = 1000;
- if (available > BUFFER_SIZE)
- bufferSize = BUFFER_SIZE;
- byte[] buffer = new byte[bufferSize];
- fin.read(buffer);
- sout.write(buffer);
- sout.flush();
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- // Ignoring this exception
- }
- continue;
- }
- break;
- }
+ def fin = bootcode.newInputStream()
+ while (true) {
+ int available = fin.available();
+ if (available > 0) {
+ int bufferSize = available;
+ int BUFFER_SIZE = 1000;
+ if (available > BUFFER_SIZE)
+ bufferSize = BUFFER_SIZE;
+ byte[] buffer = new byte[bufferSize];
+ fin.read(buffer);
+ sout.write(buffer);
+ sout.flush();
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ // Ignoring this exception
+ }
+ continue;
+ }
+ break;
+ }
}
@@ -8,6 +8,7 @@ def server = "192.168.1.95:8080";
if (SystemProperty.environment.value() == SystemProperty.environment.value().Production) {
server = "nabaztag-ae.appspot.com"
}
+
sout.println "ping "+server
sout.println "broad "+server
sout.println "xmpp_domain "+server
Oops, something went wrong.

0 comments on commit 76c3673

Please sign in to comment.