| <?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> |
| <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> |
| /* | |||||
| * 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); | |||||
| } | |||||
| } |
| 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(); | ||||
| } | } |
| 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)); |
| /* | |||||
| * 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); | |||||
| } | |||||
| } |