use of com.ichi2.anki.cardviewer.TTS in project AnkiChinaAndroid by ankichinateam.
the class ImportDialog method onCreateDialog.
@Override
public MaterialDialog onCreateDialog(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int mType = getArguments().getInt("dialogType");
Resources res = getResources();
MaterialDialog.Builder builder = new MaterialDialog.Builder(getActivity());
builder.cancelable(true);
switch(mType) {
case DIALOG_IMPORT_HINT:
{
// Instruct the user that they need to put their APKG files into the AnkiDroid directory
return builder.title(res.getString(R.string.import_title)).content(res.getString(R.string.import_hint, CollectionHelper.getCurrentAnkiDroidDirectory(getActivity()))).positiveText(res.getString(R.string.dialog_ok)).negativeText(res.getString(R.string.dialog_cancel)).onPositive((dialog, which) -> mImportDialogListener.showImportDialog(DIALOG_IMPORT_SELECT)).onNegative((dialog, which) -> dismissAllDialogFragments()).show();
}
case DIALOG_IMPORT_SELECT:
{
// Allow user to choose from the list of available APKG files
List<File> fileList = Utils.getImportableDecks(getActivity());
if (fileList.size() == 0) {
UIUtils.showThemedToast(getActivity(), getResources().getString(R.string.upgrade_import_no_file_found, "'.apkg'"), false);
return builder.showListener(dialog -> dialog.cancel()).show();
} else {
String[] tts = new String[fileList.size()];
final String[] importValues = new String[fileList.size()];
for (int i = 0; i < tts.length; i++) {
tts[i] = fileList.get(i).getName();
importValues[i] = fileList.get(i).getAbsolutePath();
}
return builder.title(res.getString(R.string.import_select_title)).items(tts).itemsCallback((materialDialog, view, i, charSequence) -> {
String importPath = importValues[i];
// If collection package, we assume the collection will be replaced
if (ImportUtils.isCollectionPackage(filenameFromPath(importPath))) {
mImportDialogListener.showImportDialog(DIALOG_IMPORT_REPLACE_CONFIRM, importPath);
// Otherwise we add the file since exported decks / shared decks can't be imported via replace anyway
} else {
mImportDialogListener.showImportDialog(DIALOG_IMPORT_ADD_CONFIRM, importPath);
}
}).show();
}
}
case DIALOG_IMPORT_ADD_CONFIRM:
{
String displayFileName = convertToDisplayName(getArguments().getString("dialogMessage"));
return builder.title(res.getString(R.string.import_title)).content(res.getString(R.string.import_message_add_confirm, filenameFromPath(displayFileName))).positiveText(res.getString(R.string.import_message_add)).negativeText(res.getString(R.string.dialog_cancel)).onPositive((dialog, which) -> {
mImportDialogListener.importAdd(getArguments().getString("dialogMessage"));
dismissAllDialogFragments();
}).show();
}
case DIALOG_IMPORT_REPLACE_CONFIRM:
{
String displayFileName = convertToDisplayName(getArguments().getString("dialogMessage"));
return builder.title(res.getString(R.string.import_title)).content(res.getString(R.string.import_message_replace_confirm, displayFileName)).positiveText(res.getString(R.string.dialog_positive_replace)).negativeText(res.getString(R.string.dialog_cancel)).onPositive((dialog, which) -> {
mImportDialogListener.importReplace(getArguments().getString("dialogMessage"));
dismissAllDialogFragments();
}).show();
}
default:
return null;
}
}
use of com.ichi2.anki.cardviewer.TTS in project Anki-Android by ankidroid.
the class AbstractFlashcardViewer method displayCardQuestion.
protected void displayCardQuestion(boolean reload) {
Timber.d("displayCardQuestion()");
sDisplayAnswer = false;
mBackButtonPressedToReturn = false;
setInterface();
mTypeAnswer.setInput("");
mTypeAnswer.updateInfo(mCurrentCard, getResources());
if (!mCurrentCard.isEmpty() && mTypeAnswer.validForEditText()) {
// Show text entry based on if the user wants to write the answer
mAnswerField.setVisibility(View.VISIBLE);
LanguageHintService.applyLanguageHint(mAnswerField, mTypeAnswer.getLanguageHint());
} else {
mAnswerField.setVisibility(View.GONE);
}
CardHtml content = mHtmlGenerator.generateHtml(mCurrentCard, reload, Side.FRONT);
updateCard(content);
hideEaseButtons();
mAutomaticAnswer.onDisplayQuestion();
// If Card-based TTS is enabled, we "automatic display" after the TTS has finished as we don't know the duration
if (!mTTS.isEnabled()) {
mAutomaticAnswer.scheduleAutomaticDisplayAnswer(mUseTimerDynamicMS);
}
Timber.i("AbstractFlashcardViewer:: Question successfully shown for card id %d", mCurrentCard.getId());
}
use of com.ichi2.anki.cardviewer.TTS in project Anki-Android by ankidroid.
the class Sound method playSoundInternal.
/**
* Plays a sound without ensuring that the playAllListener will release the audio
*/
@SuppressWarnings({ "PMD.EmptyIfStmt", "PMD.CollapsibleIfStatements" })
private void playSoundInternal(String soundPath, @NonNull OnCompletionListener playAllListener, VideoView videoView, OnErrorListener errorListener) {
Timber.d("Playing %s has listener? %b", soundPath, playAllListener != null);
Uri soundUri = Uri.parse(soundPath);
mCurrentAudioUri = soundUri;
final OnErrorListener errorHandler = errorListener == null ? (mp, what, extra, path) -> {
Timber.w("Media Error: (%d, %d). Calling OnCompletionListener", what, extra);
return false;
} : errorListener;
if ("tts".equals(soundPath.substring(0, 3))) {
// TODO: give information about did
// ReadText.textToSpeech(soundPath.substring(4, soundPath.length()),
// Integer.parseInt(soundPath.substring(3, 4)));
} else {
// Check if the file extension is that of a known video format
final String extension = soundPath.substring(soundPath.lastIndexOf(".") + 1).toLowerCase(Locale.getDefault());
boolean isVideo = Arrays.asList(VIDEO_WHITELIST).contains(extension);
if (!isVideo) {
final String guessedType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
isVideo = (guessedType != null) && guessedType.startsWith("video/");
}
// Also check that there is a video thumbnail, as some formats like mp4 can be audio only
isVideo = isVideo && hasVideoThumbnail(soundUri);
// holder
if (isVideo && videoView == null && mCallingActivity != null && mCallingActivity.get() != null) {
Timber.d("Requesting AbstractFlashcardViewer play video - no SurfaceHolder");
mPlayAllListener = playAllListener;
((AbstractFlashcardViewer) mCallingActivity.get()).playVideo(soundPath);
return;
}
// Play media
try {
// Create media player
if (mMediaPlayer == null) {
Timber.d("Creating media player for playback");
mMediaPlayer = new MediaPlayer();
} else {
Timber.d("Resetting media for playback");
mMediaPlayer.reset();
}
if (mAudioManager == null) {
mAudioManager = (AudioManager) AnkiDroidApp.getInstance().getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
}
// Provide a VideoView to the MediaPlayer if valid video file
if (isVideo && videoView != null) {
mMediaPlayer.setDisplay(videoView.getHolder());
mMediaPlayer.setOnVideoSizeChangedListener((mp, width, height) -> configureVideo(videoView, width, height));
}
mMediaPlayer.setOnErrorListener((mp, which, extra) -> errorHandler.onError(mp, which, extra, soundPath));
// Setup the MediaPlayer
mMediaPlayer.setDataSource(AnkiDroidApp.getInstance().getApplicationContext(), soundUri);
mMediaPlayer.setAudioAttributes(new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build());
mMediaPlayer.setOnPreparedListener(mp -> {
Timber.d("Starting media player");
mMediaPlayer.start();
});
mMediaPlayer.setOnCompletionListener(playAllListener);
mMediaPlayer.prepareAsync();
Timber.d("Requesting audio focus");
// Set mAudioFocusRequest for API 26 and above.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAudioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK).setOnAudioFocusChangeListener(afChangeListener).build();
}
CompatHelper.getCompat().requestAudioFocus(mAudioManager, afChangeListener, mAudioFocusRequest);
} catch (Exception e) {
Timber.e(e, "playSounds - Error reproducing sound %s", soundPath);
if (!errorHandler.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNSUPPORTED, 0, soundPath)) {
Timber.d("Force playing next sound.");
playAllListener.onCompletion(mMediaPlayer);
}
}
}
}
use of com.ichi2.anki.cardviewer.TTS in project Anki-Android by Ramblurr.
the class DeckPicker method onPrepareDialog.
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
Resources res = getResources();
StyledDialog ad = (StyledDialog) dialog;
switch(id) {
case DIALOG_DELETE_DECK:
if (!AnkiDroidApp.colIsOpen() || mDeckList == null || mDeckList.size() == 0) {
return;
}
boolean isDyn = AnkiDroidApp.getCol().getDecks().isDyn(mCurrentDid);
if (isDyn) {
ad.setMessage(String.format(res.getString(R.string.delete_cram_deck_message), "\'" + AnkiDroidApp.getCol().getDecks().name(mCurrentDid) + "\'"));
} else {
ad.setMessage(String.format(res.getString(R.string.delete_deck_message), "\'" + AnkiDroidApp.getCol().getDecks().name(mCurrentDid) + "\'"));
}
break;
case DIALOG_CONTEXT_MENU:
if (!AnkiDroidApp.colIsOpen() || mDeckList == null || mDeckList.size() == 0) {
return;
}
mCurrentDid = Long.parseLong(mDeckList.get(mContextMenuPosition).get("did"));
try {
ad.changeListItem(CONTEXT_MENU_COLLAPSE_DECK, getResources().getString(AnkiDroidApp.getCol().getDecks().get(mCurrentDid).getBoolean("collapsed") ? R.string.contextmenu_deckpicker_inflate_deck : R.string.contextmenu_deckpicker_collapse_deck));
} catch (NotFoundException e) {
// do nothing
} catch (JSONException e) {
// do nothing
}
ad.setTitle(AnkiDroidApp.getCol().getDecks().name(mCurrentDid));
break;
case DIALOG_IMPORT_LOG:
case DIALOG_SYNC_LOG:
case DIALOG_SYNC_SANITY_ERROR:
// If both have text, separate them by a new line.
if (!TextUtils.isEmpty(mDialogMessage) && !TextUtils.isEmpty(mSyncMessage)) {
ad.setMessage(mDialogMessage + "\n\n" + mSyncMessage);
} else if (!TextUtils.isEmpty(mDialogMessage)) {
ad.setMessage(mDialogMessage);
} else {
ad.setMessage(mSyncMessage);
}
break;
case DIALOG_DB_ERROR:
mLoadFailed = false;
ad.getButton(Dialog.BUTTON3).setEnabled(hasErrorFiles());
break;
case DIALOG_LOAD_FAILED:
mLoadFailed = true;
if (mOpenCollectionDialog != null && mOpenCollectionDialog.isShowing()) {
mOpenCollectionDialog.setMessage(res.getString(R.string.col_load_failed));
}
break;
case DIALOG_ERROR_HANDLING:
ArrayList<String> options = new ArrayList<String>();
ArrayList<Integer> values = new ArrayList<Integer>();
if (AnkiDroidApp.getCol() == null) {
// retry
options.add(res.getString(R.string.backup_retry_opening));
values.add(0);
} else {
// fix integrity
options.add(res.getString(R.string.check_db));
values.add(1);
}
// repair db with sqlite
options.add(res.getString(R.string.backup_error_menu_repair));
values.add(2);
// // restore from backup
options.add(res.getString(R.string.backup_restore));
values.add(3);
// delete old collection and build new one
options.add(res.getString(R.string.backup_full_sync_from_server));
values.add(4);
// delete old collection and build new one
options.add(res.getString(R.string.backup_del_collection));
values.add(5);
String[] titles = new String[options.size()];
mRepairValues = new int[options.size()];
for (int i = 0; i < options.size(); i++) {
titles[i] = options.get(i);
mRepairValues[i] = values.get(i);
}
ad.setItems(titles, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch(mRepairValues[which]) {
case 0:
loadCollection();
return;
case 1:
integrityCheck();
return;
case 2:
showDialog(DIALOG_REPAIR_COLLECTION);
return;
case 3:
showDialog(DIALOG_RESTORE_BACKUP);
return;
case 4:
showDialog(DIALOG_FULL_SYNC_FROM_SERVER);
return;
case 5:
showDialog(DIALOG_NEW_COLLECTION);
return;
}
}
});
break;
case DIALOG_IMPORT_SELECT:
List<File> fileList = Utils.getImportableDecks();
if (fileList.size() == 0) {
Themes.showThemedToast(DeckPicker.this, getResources().getString(R.string.upgrade_import_no_file_found), false);
}
ad.setEnabled(fileList.size() != 0);
String[] tts = new String[fileList.size()];
mImportValues = new String[fileList.size()];
for (int i = 0; i < tts.length; i++) {
tts[i] = fileList.get(i).getName().replace(".apkg", "");
mImportValues[i] = fileList.get(i).getAbsolutePath();
}
ad.setItems(tts, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mImportPath = mImportValues[which];
switch(mImportMethod) {
case IMPORT_METHOD_ADD:
DeckTask.launchDeckTask(DeckTask.TASK_TYPE_IMPORT, mImportAddListener, new TaskData(AnkiDroidApp.getCol(), mImportPath, false));
mImportPath = null;
break;
case IMPORT_METHOD_REPLACE:
DeckTask.launchDeckTask(DeckTask.TASK_TYPE_IMPORT_REPLACE, mImportReplaceListener, new TaskData(AnkiDroidApp.getCol(), mImportPath));
mImportPath = null;
break;
case IMPORT_METHOD_ASK:
default:
showDialog(DIALOG_IMPORT);
}
mImportMethod = IMPORT_METHOD_ASK;
}
});
break;
}
}
use of com.ichi2.anki.cardviewer.TTS in project Anki-Android by Ramblurr.
the class ReadText method textToSpeech.
public static void textToSpeech(String text, long did, int ord, int qa) {
mTextToSpeak = text;
mQuestionAnswer = qa;
mDid = did;
mOrd = ord;
String language = getLanguage(mDid, mOrd, mQuestionAnswer);
if (availableTtsLocales.isEmpty()) {
Locale[] systemLocales = Locale.getAvailableLocales();
for (Locale loc : systemLocales) {
if (mTts.isLanguageAvailable(loc) == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
availableTtsLocales.add(new String[] { loc.getISO3Language(), loc.getDisplayName() });
}
}
}
// Check, if stored language is available
for (int i = 0; i < availableTtsLocales.size(); i++) {
if (language.equals(NO_TTS)) {
return;
} else if (language.equals(availableTtsLocales.get(i)[0])) {
speak(mTextToSpeak, language);
return;
}
}
// Otherwise ask
Resources res = mReviewer.getResources();
StyledDialog.Builder builder = new StyledDialog.Builder(mReviewer);
if (availableTtsLocales.size() == 0) {
builder.setTitle(res.getString(R.string.no_tts_available_title));
builder.setMessage(res.getString(R.string.no_tts_available_message));
builder.setIcon(R.drawable.ic_dialog_alert);
builder.setPositiveButton(res.getString(R.string.ok), null);
} else {
ArrayList<CharSequence> dialogItems = new ArrayList<CharSequence>();
final ArrayList<String> dialogIds = new ArrayList<String>();
builder.setTitle(R.string.select_locale_title);
// Add option: "no tts"
dialogItems.add(res.getString(R.string.tts_no_tts));
dialogIds.add(NO_TTS);
for (int i = 0; i < availableTtsLocales.size(); i++) {
dialogItems.add(availableTtsLocales.get(i)[1]);
dialogIds.add(availableTtsLocales.get(i)[0]);
}
String[] items = new String[dialogItems.size()];
dialogItems.toArray(items);
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
MetaDB.storeLanguage(mReviewer, mDid, mOrd, mQuestionAnswer, dialogIds.get(which));
speak(mTextToSpeak, dialogIds.get(which));
}
});
}
builder.create().show();
}
Aggregations