Working with FreeTTS and JSAPI - jsapi

I am working on a project where I needed Text to speech conversion. I Downloaded this FreeTTS 1.2 and to get familiar with the working I started making a simple spell bee program where the words will be spoken by the application and you have to spell it correctly. But I'm facing problems with functions like the voice is same irrespective of the changes I make. Like the initially the code I found had following parameters in the Voice() constructor
Voice kevin = new Voice("kevin",
Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null);
but then I changed it to
Voice kevin = new Voice("Different1",
Voice.GENDER_FEMALE, Voice.AGE_MIDDLE_ADULT, null);
and still the voice is same. There is a speech.properties file which came with FreeTTS and to run the code I have to paste that file in my home folder. I have searched a lot of links to solve this even checked the Javadocs for JSAPI and FreeTTS. The only thing I got in common was something called MBrola. I don't what this is but when I run the code, the console also gives a message related to it.
System property "mbrola.base" is undefined. Will not use MBROLA voices.
Here's is the whole code:
package game;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Locale;
import javax.speech.Central;
import javax.speech.synthesis.SpeakableAdapter;
import javax.speech.synthesis.SpeakableEvent;
import javax.speech.synthesis.Synthesizer;
import javax.speech.synthesis.SynthesizerModeDesc;
import javax.speech.synthesis.Voice;
public class MixedVoices {
private final static void usage() {
System.out.println("MixedVoices [-showEvents] [-showPropertyChanges]");
}
/**
* Returns a "no synthesizer" message, and asks
* the user to check if the "speech.properties" file is
* at <code>user.home</code> or <code>java.home/lib</code>.
*
* #return a no synthesizer message
*/
static private String noSynthesizerMessage(String synthesizer)
{
String message =
"Cannot find " + synthesizer + ".\n" +
"This may be the result of any number of problems. It's\n" +
"typically due to a missing \"speech.properties\" file that\n" +
"should be at either of these locations: \n\n";
message += "user.home : " + System.getProperty("user.home") + "\n";
message += "java.home/lib: " + System.getProperty("java.home") +
File.separator + "lib\n\n" +
"Another cause of this problem might be corrupt or missing\n" +
"voice jar files in the freetts lib directory. This problem\n" +
"also sometimes arises when the freetts.jar file is corrupt\n" +
"or missing. Sorry about that. Please check for these\n" +
"various conditions and then try again.\n";
return message;
}
public static void main(String[] argv)
{
boolean showEvents = false;
boolean showPropertyChanges = false;
for (int i = 0; i < argv.length; i++)
{
if (argv[i].equals("-showEvents")) {
showEvents = true;
} else if (argv[i].equals("-showPropertyChanges")) {
showPropertyChanges = true;
} else {
usage();
System.exit(0);
}
}
System.out.println(" ** Mixed Voices - JSAPI Demonstration program **");
/* kevin in an 8khz general domain diphone voice
*/
Voice kevin = new Voice("kevin",
Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null);
/* kevin16 in a 16khz general domain diphone voice
*/
Voice kevinHQ = new Voice("kevin16",
Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null);
try {
/* Find a synthesizer that has the general domain voice
* we are looking for. NOTE: this uses the Central class
* of JSAPI to find a Synthesizer. The Central class
* expects to find a speech.properties file in user.home
* or java.home/lib.
*
* If your situation doesn't allow you to set up a
* speech.properties file, you can circumvent the Central
* class and do a very non-JSAPI thing by talking to
* FreeTTSEngineCentral directly. See the WebStartClock
* demo for an example of how to do this.
*/
SynthesizerModeDesc generalDesc = new SynthesizerModeDesc(
null, // engine name
"general", // mode name
Locale.US, // locale
null, // running
null); // voice
final Synthesizer synthesizer1 =
Central.createSynthesizer(generalDesc);
if (synthesizer1 == null) {
System.err.println(
noSynthesizerMessage("general domain synthesizer"));
System.exit(1);
}
/* Find a synthesizer that has the time domain voice.
*/
SynthesizerModeDesc limitedDesc = new SynthesizerModeDesc(
null, // engine name
"time", // mode name
Locale.US, // locale
null, // running
null); // voice
final Synthesizer synthesizer2 =
Central.createSynthesizer(limitedDesc);
if (synthesizer2 == null) {
System.err.println(
noSynthesizerMessage("time domain synthesizer"));
System.exit(1);
}
System.out.print(" Allocating synthesizers...");
synthesizer1.allocate();
synthesizer2.allocate();
/* get general domain synthesizer ready to speak
*/
System.out.print("Loading voices...");
synthesizer1.getSynthesizerProperties().setVoice(kevinHQ);
synthesizer1.getSynthesizerProperties().setVoice(kevin);
if (showPropertyChanges) {
synthesizer1.getSynthesizerProperties().addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(
PropertyChangeEvent pce) {
if (pce.getNewValue() instanceof Voice) {
String newVoice =
((Voice) pce.getNewValue()).getName();
System.out.println(
" PCE Voice changed to " + newVoice);
}
else {
System.out.println(
" PCE " + pce.getPropertyName()
+ " changed from "
+ pce.getOldValue() + " to " +
pce.getNewValue() + ".");
}
}
});
}
if (showEvents) {
synthesizer1.addSpeakableListener(
new SpeakableAdapter() {
public void markerReached(SpeakableEvent e) {
dumpEvent(e);
}
public void speakableCancelled(SpeakableEvent e) {
dumpEvent(e);
}
public void speakableEnded(SpeakableEvent e) {
dumpEvent(e);
}
public void speakablePaused(SpeakableEvent e) {
dumpEvent(e);
}
public void speakableResumed(SpeakableEvent e) {
dumpEvent(e);
}
public void speakableStarted(SpeakableEvent e) {
dumpEvent(e);
}
public void topOfQueue(SpeakableEvent e) {
dumpEvent(e);
}
public void wordStarted(SpeakableEvent e) {
dumpEvent(e);
}
private void dumpEvent(SpeakableEvent e) {
System.out.println(" EVT: " + e.paramString()
+ " source: " + e.getSource());
}
});
}
System.out.println("And here we go!");
synthesizer1.resume();
synthesizer2.resume();
// speak the "Hello world" string
synthesizer1.speakPlainText("Hello! My name is Kevin.", null);
synthesizer1.speakPlainText("I am a die phone synthesizer", null);
synthesizer1.speakPlainText("I have a friend named Alan.", null);
synthesizer1.speakPlainText("Listen to him count!", null);
// get synth2 ready to speak
synthesizer2.waitEngineState(Synthesizer.ALLOCATED);
synthesizer2.resume();
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer2.speakPlainText("1 2 3 4 5 6 7 8 9 ten", null);
synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.speakPlainText("Now listen to me count!", null);
synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 10.", null);
synthesizer1.speakPlainText(
"Now, let's try that a little bit faster.", null);
synthesi zer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setSpeakingRate(240.0f);
synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 10.", null);
synthesizer1.speakPlainText("That's pretty fast.", null);
synthesizer1.speakPlainText("Now lets go very slow.", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setSpeakingRate(80.0f);
synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 10.", null);
synthesizer1.speakPlainText("That is pretty slow.", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setSpeakingRate(150.0f);
synthesizer1.speakPlainText("Now back to normal", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setPitch(200);
synthesizer1.speakPlainText("I can talk very high.", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setPitch(50);
synthesizer1.speakPlainText("and I can talk very low.", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setPitch(100);
synthesizer1.getSynthesizerProperties().setVolume(.8f);
synthesizer1.speakPlainText("and I can talk very softly.", null);
synt hesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setVolume(1.0f);
synthesizer1.speakPlainText(
"I can talk with a higher quality voice", null);
synthesizer1.speakPlainText(
"Here is a low quality tongue twister. "
+ "She sells seashells by the seashore.", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.getSynthesizerProperties().setVoice(kevinHQ);
synthesizer1.speakPlainText("And this is high quality. "
+ "She sells seashells by the seashore.", null);
synthesizer1.speakPlainText(
"The funny thing is, I do not have a tongue.", null);
synthesizer1.speakPlainText(
"Hey Alan, what time is it where you are right now?", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer2.speakPlainText(
"the time is now twenty past six.", null);
synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.speakPlainText("Is that the exact time?", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer2.speakPlainText("Almost", null);
synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.speakPlainText(
"Is it twenty past six In the morning or the evening?", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer2.speakPlainText("in the morning.", null);
synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.speakPlainText(
"Alan and I can talk at the same time", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.speakPlainText("1 2 3 4 5 6 7 8 9 11 12", null);
synthesizer2.speakPlainText("1 2 3 4 5 6 7 8 9", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer2.waitEngineState(Synthesizer.QUEUE_EMPTY);
synthesizer1.speakPlainText( "That is a bit confusing.", null);
synthesizer1.speakPlainText( "Well, thanks. This was fun.", null);
synthesizer1.speakPlainText("Goodbye everyone.", null);
synthesizer1.waitEngineState(Synthesizer.QUEUE_EMPTY);
// clean up
synthesizer1.deallocate();
synthesizer2.deallocate();
}
catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
}

The voices that you have access to is controlled by the VoiceManager class. It will search for voice packages installed in your system via a couple of different methods. By default you will have 3 voices installed: "alan", "kevin", and "kevin16". You need to install other voice packages (e.g. CMUArctic or MBROLA) before you can use voices other than the 3 default voices.
However, once you've installed a new voice (look at the corresponding websites for install instructions), you will also need to add that Voice Directory to the correct place, and add its name to a text file that lists all installed voices. Take a look at the Programmer's Guide under Installing Voice Packages. For reference, I ended up adding my new voice package paths to the voices.txt file next to the freetts.jar that I was using (which was a bit ttricky- I forgot I had added it to my Library/Java/Extensions folder on my Mac, so you may have to add the voices.txt file there).
You can check which voice are available with the following code:
VoiceManager voiceManager = VoiceManager.getInstance();
Voice[] voices = voiceManager.getVoices();
for (int i = 0; i < voices.length; i++){
System.out.print( "voice name is: " + voices[i].getName() +"\n");
}
Once you've successfully added the Voice Directories for the voices you've installed, you should see them listed when you run that code.

Related

How can Android BLE read more than 20 bytes in Delphi FMX 10.3 API is(API 29)

In Delphi FMX 10.3, I can scan for a BLE device and can connect to it, and can also receive data, but when sending data more than 20 bytes, the app cannot receive data. I know modifying the MTU to greater than 20 will work ok.
In Android Studio, it is easy to implement, but in Delphi FMX I cannot find any support.
Android Studio sample:
private void setMtu(int setMtu) {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
device.connectGatt(DemoActivity.this, true, new BluetoothGattCallback() {
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (setMtu > 23 && setMtu < 512) {
gatt.requestMtu(setMtu);
}
}
}
#Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
mMtu = mtu;
if (BluetoothGatt.GATT_SUCCESS == status && setMtu == mtu) {
LogUtils.d("MTU change success = " + mtu);
} else {
LogUtils.d("MTU change fail!");
}
}
});
}
});
}
But in Delphi, how to implement this?
As far as I understand, 20 bytes is the maximum packet size:
"BLE allow you transfer maximum is 20 bytes."
"You are correct that the BLE specification doesn't allow write operations to exceed 20 bytes."
Maximum packet length for Bluetooth LE? - Stack Overflow
I would look at connection type.
GATT describes in detail how attributes (data) are transferred once devices have a dedicated connection.

Getting Error code -1 (HTTP_CONNECTION_REFUSED) after first connection

I have a setup with two ESP8266 chips.
One is AP and listening for alarms from other ESP8266 in WiFi mode.
AP is an access point accepting get requests from "alarm" chips.
My problem is that when the first GET request has been handled (succesfully) by the AP, it is no longer possible to make more requests unless the AP chip is reset.
Connection to the AP WiFI goes fine apparently but the actual get request only works on the first attempt after reset, the next ones all return error code -1 to the client.
Code from the AP chip:
void setupAP()
{
WiFi.mode(WIFI_AP);
String AP_NameString = "KEEP SAFE " + deviceID;
char AP_NameChar[AP_NameString.length() + 1];
memset(AP_NameChar, 0, AP_NameString.length() + 1);
for (int i = 0; i < AP_NameString.length(); i++)
AP_NameChar[i] = AP_NameString.charAt(i);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); // subnet FF FF FF 00
WiFi.softAP(AP_NameChar, WiFiAPPSK);
yield();
activeMenu = mainMenu;
server.on("/setup", handleWebRequest_Setup); //Associate the handler function to the path
server.on("/confirm", handleWebRequest_Confirm); //Associate the handler function to the path
server.on("/alarm", HTTP_GET, handleWebRequest_Alarm);
server.begin(); //Start the server
Serial.println("Server listening");
}
void handleWebRequest_Alarm(){
Serial.println("Client connected");
sensorAlarmPostback(server);
String s = "";
s += "<!DOCTYPE HTML>\r\n<html>\r\n";
s += "OK";
s += "</html>\n";
// Send the response to the client
Serial.println("Send OK to client");
server.send(200, "text/html", s);
Serial.println("OK Has been sent to the client");
}
void sensorAlarmPostback(ESP8266WebServer serv) {
Serial.println(String("Alaram recieved from : " + serv.arg("id")));
for (int i = 0; i < maxSensors; i++)
{
if (sensors[i].ID == serv.arg("id"))
sensors[i].alarm = true;
yield();
}
Serial.println("Sensor alarm flag has been set");
}
Code from the "sender" (alarm) chip:
void loop() {
initWifi();
publishAlarm();
WiFi.disconnect();
delay(30 * 1000); // Wait 30 seconds before next alarm
}
void initWifi() {
WiFi.disconnect();
WiFi.mode(WIFI_STA); // added in V 3.1a to disable AP_SSID publication in Client mode - default was WIFI_AP_STA
WiFi.begin(ssid.c_str(), password.c_str());
int retryCount = 0;
while (WiFi.status() != WL_CONNECTED && retryCount < 10) {
delay(2000);
retryCount++;
}
if (WiFi.status() != WL_CONNECTED)
Serial.println("WiFi ERROR");
else
Serial.println("WiFi Connected");
delay(500);
}
void publishAlarm(){
HTTPClient http;
String postStr = "?id=" + AlarmID;
postStr.replace("\r", "");
postStr.replace("\n", "");
Serial.println("String is");
Serial.println(postStr);
Serial.println("Connecting to Controller...");
String PostURL = "http://10.10.10.1/alarm" + postStr;
Serial.println("URL is: " + PostURL);
http.begin(PostURL);
int httpCode = http.GET();
if (httpCode > 0)
{
Serial.println("httpCode > 0");
yield();
delay(100);
http.end();
}
else
{
Serial.println("Error in upload " + String(httpCode));
yield();
delay(100);
http.end();
}
}
I realize that there is a lot of unneeded stuff in the code, but I have been trying almost everything. I just don't get it, and I have the same problem in other projects as well. The chips I use are Wemos D1 Minis and various NodeMCU dev. boards. Does not seem to be related to a specific board.
Update - SOLVED
I decided to wipe my entire development environment and re-install.
It wasn't that big of a deal.
And after a recompile and deployment to the chip (The AP Chip) it works as it alwas should have.
Oh well ....
Hope this helps someone if they end up in the same situation.
Now to cleaning up the code

Codename One - Can't read from socket on real device

I'm developing an iOS app, using Codename One. I extended the SocketConnection class, in order to receive data from a server.
class CustomSocketConnection extends SocketConnection {
private OutputStream os;
private InputStream is;
private InputStreamReader isr;
private String rawMessage;
public CustomSocketConnection(){
os = null;
is = null;
isr = null;
rawMessage = null;
}
public synchronized String getRawMessage(){
return rawMessage;
}
#Override
public void connectionError(int errorCode, String message) {
rawMessage = null;
ToastBar.showErrorMessage("Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
System.out.println(">>>CustomSocketConnection, connectionError. Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
}
#Override
public void connectionEstablished(InputStream is, OutputStream os) {
System.out.println(">>>CustomSocketConnection, connectionEstablished");
char termination = '\n';
int length = 1024;
char[] buffer = new char[length];
byte[] bufferByte = new byte[length];
StringBuilder stringBuilder = new StringBuilder();
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima del while");
try {
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima della read");
while(true){
System.out.println(">>>CustomSocketConnection, loop di read, inizio");
int read = isr.read();
System.out.println(">>>CustomSocketConnection, loop di read, subito dopo la read");
char c = (char) read;
if (read == -1) rawMessage = null;
System.out.println(">>>CustomSocketConnection, loop di read, letto: " + c);
while(c != termination){
stringBuilder.append(c);
read = isr.read();
c = (char) read;
if (read == -1) rawMessage = null;
}
rawMessage = stringBuilder.toString();
if(rawMessage != null) doActions(rawMessage);
//System.out.println(">>>CustomSocketConnection, connectionEstablished, ho letto: " + rawMessage + "FINE");
}
}
catch (IOException ex) {
System.out.println(">>>CustomSocketConnection, connectionEstablished, errore: " + ex.getMessage());
}
System.out.println(">>>CustomSocketConnection, connectionEstablished, dopo il while");
}
private void doActions(String msg){
//do something
}
}
In the connectionEstablished method, I read data from server, using the read method of the InputStreamReader class.
If I run the app on the simulator, it works properly and it receives data from server. When I launch the app on real devices (iPad mini, 32-bit device, iOS version 8.1.1 12B435, more details here; iPhone 7s, 64-bit device, iOS version 11.2.5 15D60), the read method doesn't receive data from server. In fact, I can see the string printed by the println before the read method, but I can't see the string printed by the println after the read method.
The issue is not server-side, because I developed an Android app and it receive data from the same server. There aren't firewall restrictions or other network limitations: Android app and the Codename One simulator both receive data when connected on the same local network of the server or from another one.
What's wrong?
Solved using InputStream instead of InputStreamReader.
#Override
public void connectionEstablished(InputStream is, OutputStream os) {
System.out.println(">>>CustomSocketConnection, connectionEstablished");
char termination = '\n';
StringBuilder stringBuilder = new StringBuilder();
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima del while");
try {
System.out.println(">>>CustomSocketConnection, connectionEstablished, prima della read");
while(true){
System.out.println(">>>CustomSocketConnection, loop di read, inizio");
int read = is.read();
System.out.println(">>>CustomSocketConnection, loop di read, subito dopo la read");
char c = (char) read;
if (read == -1) rawMessage = null;
System.out.println(">>>CustomSocketConnection, loop di read, letto: " + c);
while(c != termination){
stringBuilder.append(c);
read = is.read();
c = (char) read;
if (read == -1) rawMessage = null;
}
rawMessage = stringBuilder.toString();
if(rawMessage != null) doActions(rawMessage);
//System.out.println(">>>CustomSocketConnection, connectionEstablished, ho letto: " + rawMessage + "FINE");
}
}
catch (IOException ex) {
System.out.println(">>>CustomSocketConnection, connectionEstablished, errore: " + ex.getMessage());
}
System.out.println(">>>CustomSocketConnection, connectionEstablished, dopo il while");
}
Can anyone explain me why it's working with InputStream?

Printer doesn't work receiving esc/p commands

I'm trying to start working with ESC/P commands with a label printer Brother TD-4000.
I have tested the properly software of the printer, P-touch Editor 5.1, and I can made several labels, the printer works well but, when I'm tried to make my own labels from Java code, the printer doesn't work at all, it doesn't response.
I've have worked with other label printers with EZPL and I hadn't any problems with this method.
What do I can try now?
My code is very simple, here you are:
public class PrintESC_P {
public static void main(String[] args) {
PrintService printService = null;
String printerName = "Brother TD-4000";
HashAttributeSet attributeSet = new HashAttributeSet();
attributeSet.add(new PrinterName(printerName, null));
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, attributeSet);
if (services.length == 0) {
throw new IllegalArgumentException("Printer not found.");
} else if (services.length > 1) {
System.out.println("Found more than one printer. Only the first printer will be used.");
}
printService = services[0];
System.out.println("Printer found: "+printService.getName());
try {
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
String _ESC_P_Code = "ESC i a 00h\r\n" +
"ESC #\r\n" +
"ESC i L 01h\r\n" +
"ESC ( C 02h 00h FCh 02h\r\n" +
"ESC $ 2Bh 00h\r\n" +
"ESC ( V 02h 00h 6Dh 01h\r\n" +
"ESC k 0bh\r\n" +
"ESC X 00h 64h 00h\r\n" +
"PRINTER TEST\r\n" +
"ESC i C\r\n" +
"FF\r\n";
SimpleDoc doc = new SimpleDoc(_ESC_P_Code.getBytes(), flavor, null);
DocPrintJob job = printService.createPrintJob();
job.print(doc, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Thanks in advance!
Finally, I had to change the way to send the code to the printer.
Instead of a String I had to send the code in a byte array in hexadecimal format.
Now the printer works well and recognizes the commands.
I believe your problem is you are including spaces in the string, which is not allowed in ESC/P language.
Instead of (incorrect) string:
String _ESC_P_Code = "ESC i a 00h\r\n"
You must write:
String _ESC_P_Code = "\x1Bia\x00" // that is 4 bytes: 0x1B, 0x69, 0x61, 0x00
You do not have to follow the way I wrote the string, just make sure you are sending raw data.
I solved my problems printing in ESC/P by first debugging the program and viewing the string sent to the printer in binary form, and manually checking if there are no extra bytes - printer will not accept any such errors.

Redirecting output of an external application started with glib

I'm trying to use vala to start an external application using GLib with spawn_command_line_sync().
According to the documentation (http://valadoc.org/#!api=glib-2.0/GLib.Process.spawn_sync) you can pass a string to store the output of the external application.
While this works fine when starting a script which prints a couple of lines, I need to call a program which will print the content of a binary file.
(for example "cat /usr/bin/apt-get")
Is there any way how I can receive the output of the external program not in a string, but in a DataStream or something like that ?
I'm planning to write the ouput of the external program to a file, so just calling "cat /usr/bin/apt-get > outputfile" would be an alternative (not as nice), but it doesn't seem to work.
Anyway I would prefer it to get some kind of Output Stream.
I would appreciate any help.
Code im using:
using GLib;
static void main(string[] args) {
string execute = "cat /usr/bin/apt-get";
string output = "out";
try {
GLib.Process.spawn_command_line_sync(execute, out output);
} catch (SpawnError e) {
stderr.printf("spawn error!");
stderr.printf(e.message);
}
stdout.printf("Output: %s\n", output);
}
GLib.Process.spawn_async_with_pipes will let you do just that. It spawns the processes and returns a file descriptor for each of stdout, stderr, and stdin. There's a sample of code in the ValaDoc on how to set up IOChannels to monitor the output.
Thanks for that, I must have overread spawn_async_with_pipes() returning ints and not strings.
Is there anything wrong with doing it this way ?
(besides the buffer size of 1)
using GLib;
static void main(string[] args) {
string[] argv = {"cat", "/usr/bin/apt-get"};
string[] envv = Environ.get();
int child_pid;
int child_stdin_fd;
int child_stdout_fd;
int child_stderr_fd;
try {
Process.spawn_async_with_pipes(
".",
argv,
envv,
SpawnFlags.SEARCH_PATH,
null,
out child_pid,
out child_stdin_fd,
out child_stdout_fd,
out child_stderr_fd);
} catch (SpawnError e) {
stderr.printf("spawn error!");
stderr.printf(e.message);
return;
}
FileStream filestream1 = FileStream.fdopen(child_stdout_fd, "r");
FileStream filestream2 = FileStream.open("./stdout", "w");
uint8 buf[1];
size_t t;
while ((t = filestream1.read(buf, 1)) != 0) {
filestream2.write(buf, 1);
}
}

Resources