Browse Source

Add the ability to import an eSpeak dictionary file from the SD card.

master
Reece H. Dunn 11 years ago
parent
commit
9c00360347

+ 14
- 0
android/res/layout/import_voice_preference.xml View File

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/dictionaries"
android:gravity="bottom"
android:layout_gravity="center_vertical" />

</LinearLayout>

+ 2
- 0
android/res/values/strings.xml View File

<string name="variant_old">Old</string> <string name="variant_old">Old</string>
<string name="variant_croak">Croak</string> <string name="variant_croak">Croak</string>
<string name="variant_whisper">Whisper</string> <string name="variant_whisper">Whisper</string>
<string name="import_voice_title">Import eSpeak dictionary</string>
<string name="import_voice_description">Import an eSpeak voice dictionary file from the SD card.</string>
</resources> </resources>

+ 69
- 0
android/src/com/reecedunn/espeak/FileListAdapter.java View File

/*
* Copyright (C) 2013 Reece H. Dunn
*
* 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.
*/

package com.reecedunn.espeak;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.io.File;

public class FileListAdapter extends ArrayAdapter<File>
{
private final LayoutInflater mInflater;

static class ViewHolder
{
public TextView text;
}

public FileListAdapter(Activity context, File[] resources)
{
super(context, android.R.layout.simple_list_item_1, resources);
mInflater = context.getLayoutInflater();
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
holder = new ViewHolder();
holder.text = (TextView)convertView.findViewById(android.R.id.text1);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder)convertView.getTag();
}

File file = getItem(position);
holder.text.setText(file.getName());
return convertView;
}

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent)
{
return getView(position, convertView, parent);
}
}

+ 24
- 4
android/src/com/reecedunn/espeak/FileUtils.java View File



public class FileUtils { public class FileUtils {
public static String read(File file) throws IOException { public static String read(File file) throws IOException {
return read(new FileInputStream(file), (int)file.length());
return readByteArray(new FileInputStream(file), (int)file.length()).toString();
} }


public static String read(InputStream stream) throws IOException { public static String read(InputStream stream) throws IOException {
return read(stream, stream.available());
return readByteArray(stream, stream.available()).toString();
} }


public static String read(InputStream stream, int length) throws IOException { public static String read(InputStream stream, int length) throws IOException {
return readByteArray(stream, length).toString();
}

public static byte[] readBinary(File file) throws IOException {
return readByteArray(new FileInputStream(file), (int)file.length()).toByteArray();
}

public static byte[] readBinary(InputStream stream) throws IOException {
return readByteArray(stream, stream.available()).toByteArray();
}

public static byte[] readBinary(InputStream stream, int length) throws IOException {
return readByteArray(stream, length).toByteArray();
}

private static ByteArrayOutputStream readByteArray(InputStream stream, int length) throws IOException {
ByteArrayOutputStream content = new ByteArrayOutputStream(length); ByteArrayOutputStream content = new ByteArrayOutputStream(length);
int c = stream.read(); int c = stream.read();
while (c != -1) while (c != -1)
content.write((byte)c); content.write((byte)c);
c = stream.read(); c = stream.read();
} }
return content.toString();
return content;
} }


public static void write(File outputFile, String contents) throws IOException { public static void write(File outputFile, String contents) throws IOException {
write(outputFile, contents.getBytes());
}

public static void write(File outputFile, byte[] contents) throws IOException {
FileOutputStream outputStream = new FileOutputStream(outputFile); FileOutputStream outputStream = new FileOutputStream(outputFile);
try { try {
outputStream.write(contents.getBytes(), 0, contents.length());
outputStream.write(contents, 0, contents.length);
} finally { } finally {
outputStream.close(); outputStream.close();
} }

+ 13
- 0
android/src/com/reecedunn/espeak/TtsSettingsActivity.java View File

import android.preference.PreferenceGroup; import android.preference.PreferenceGroup;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;


import com.reecedunn.espeak.preference.ImportVoicePreference;
import com.reecedunn.espeak.preference.SeekBarPreference; import com.reecedunn.espeak.preference.SeekBarPreference;
import com.reecedunn.espeak.preference.SpeakPunctuationPreference; import com.reecedunn.espeak.preference.SpeakPunctuationPreference;
import com.reecedunn.espeak.preference.VoiceVariantPreference; import com.reecedunn.espeak.preference.VoiceVariantPreference;
} }
} }


private static Preference createImportVoicePreference(Context context) {
final String title = context.getString(R.string.import_voice_title);

final ImportVoicePreference pref = new ImportVoicePreference(context);
pref.setTitle(title);
pref.setDialogTitle(title);
pref.setOnPreferenceChangeListener(mOnPreferenceChanged);
pref.setDescription(R.string.import_voice_description);
return pref;
}

private static Preference createVoiceVariantPreference(Context context, VoiceSettings settings, int titleRes) { private static Preference createVoiceVariantPreference(Context context, VoiceSettings settings, int titleRes) {
final String title = context.getString(titleRes); final String title = context.getString(titleRes);


SpeechSynthesis engine = new SpeechSynthesis(context, null); SpeechSynthesis engine = new SpeechSynthesis(context, null);
VoiceSettings settings = new VoiceSettings(PreferenceManager.getDefaultSharedPreferences(context), engine); VoiceSettings settings = new VoiceSettings(PreferenceManager.getDefaultSharedPreferences(context), engine);


group.addPreference(createImportVoicePreference(context));
group.addPreference(createVoiceVariantPreference(context, settings, R.string.espeak_variant)); group.addPreference(createVoiceVariantPreference(context, settings, R.string.espeak_variant));
group.addPreference(createSpeakPunctuationPreference(context, settings, R.string.espeak_speak_punctuation)); group.addPreference(createSpeakPunctuationPreference(context, settings, R.string.espeak_speak_punctuation));
group.addPreference(createSeekBarPreference(context, engine.Rate, VoiceSettings.PREF_RATE, R.string.setting_default_rate)); group.addPreference(createSeekBarPreference(context, engine.Rate, VoiceSettings.PREF_RATE, R.string.setting_default_rate));

+ 117
- 0
android/src/com/reecedunn/espeak/preference/ImportVoicePreference.java View File

/*
* Copyright (C) 2013 Reece H. Dunn
*
* 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.
*/

package com.reecedunn.espeak.preference;

import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Environment;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Spinner;

import com.reecedunn.espeak.CheckVoiceData;
import com.reecedunn.espeak.DownloadVoiceData;
import com.reecedunn.espeak.FileListAdapter;
import com.reecedunn.espeak.FileUtils;
import com.reecedunn.espeak.R;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;

public class ImportVoicePreference extends DialogPreference {
private File mRoot;
private Spinner mDictionaries;

public ImportVoicePreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setDialogLayoutResource(R.layout.import_voice_preference);
setLayoutResource(R.layout.information_view);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);

mRoot = Environment.getExternalStorageDirectory();
}

public ImportVoicePreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ImportVoicePreference(Context context) {
this(context, null);
}

public void setDescription(int resId) {
callChangeListener(getContext().getString(resId));
}

@Override
protected View onCreateDialogView() {
View root = super.onCreateDialogView();
mDictionaries = (Spinner)root.findViewById(R.id.dictionaries);
return root;
}

@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
File[] dictionaries = mRoot.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return !file.isDirectory() && file.getName().endsWith("_dict");
}
});
Arrays.sort(dictionaries);
mDictionaries.setAdapter(new FileListAdapter((Activity)getContext(), dictionaries));
}

@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
new AsyncTask<Object,Object,Object>() {
@Override
protected Object doInBackground(Object... objects) {
File source = (File)mDictionaries.getSelectedItem();
File destination = new File(CheckVoiceData.getDataPath(getContext()), source.getName());
try {
byte[] data = FileUtils.readBinary(source);
FileUtils.write(destination, data);
} catch (IOException e) {
}
return null;
}

@Override
protected void onPostExecute(Object object) {
final Intent intent = new Intent(DownloadVoiceData.BROADCAST_LANGUAGES_UPDATED);
getContext().sendBroadcast(intent);
}
}.execute();
break;
}
super.onClick(dialog, which);
}
}

Loading…
Cancel
Save