Search in sources :

Example 6 with TTS

use of com.ichi2.anki.cardviewer.TTS in project AnkiChinaAndroid by ankichinateam.

the class ReadText method selectTtsForVip.

public static void selectTtsForVip(String text, long cid, long did, int ord, Sound.SoundSide qa, boolean vipSpeak) {
    Timber.w("selectTts:%s", vipSpeak);
    // TODO: Consolidate with ReadText.readCardSide
    mTextToSpeak = text;
    mQuestionAnswer = qa;
    mDid = did;
    mOrd = ord;
    Resources res = mReviewer.get().getResources();
    final MaterialDialog.Builder builder = new MaterialDialog.Builder(mReviewer.get());
    // Build the language list if it's empty
    if (availableTtsLocales.isEmpty()) {
        buildAvailableLanguages(TextToSpeech.LANG_AVAILABLE);
    }
    if (availableTtsLocales.size() == 0) {
        Timber.w("ReadText.textToSpeech() no TTS languages available");
        builder.content(res.getString(R.string.no_tts_available_message)).iconAttr(R.attr.dialogErrorIcon).positiveText(res.getString(R.string.dialog_ok));
    } else {
        if (vipSpeak) {
            for (int i = 0; i < availableTtsLocales.size(); i++) {
                // vip里的设置,默认选择中文
                String name = availableTtsLocales.get(i).getDisplayName();
                if (name.contains("chinese") || name.contains("Chinese") || name.contains("中文") || name.contains("中国")) {
                    // 默认选择中文
                    String locale = availableTtsLocales.get(i).getISO3Language();
                    // if (!locale.equals(NO_TTS)) {
                    // speak(mTextToSpeak, locale, TextToSpeech.QUEUE_FLUSH);
                    // }
                    MetaDB.storeLanguage(mReviewer.get(), mDid, mOrd, mQuestionAnswer, locale);
                    return;
                }
            }
            CustomStyleDialog d = new CustomStyleDialog.Builder(mReviewer.get()).setCustomLayout(R.layout.dialog_common_custom_next).setTitle("首次朗读,请设置语言").centerTitle().setMessage("设置语言后,朗读效果更优,还可以选择是否自动朗读。").setPositiveButton("前往设置", (dialog, which) -> {
                dialog.dismiss();
                SpeakSettingActivity.OpenSpeakSetting(cid, did, mReviewer.get());
            }).create();
            d.show();
        }
    }
}
Also used : Context(android.content.Context) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) WindowManager(android.view.WindowManager) UtteranceProgressListener(android.speech.tts.UtteranceProgressListener) Compat(com.ichi2.compat.Compat) Timber(timber.log.Timber) ArrayList(java.util.ArrayList) TextToSpeech(android.speech.tts.TextToSpeech) Nullable(androidx.annotation.Nullable) Locale(java.util.Locale) Handler(android.os.Handler) Toast(android.widget.Toast) CompatHelper(com.ichi2.compat.CompatHelper) View(android.view.View) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) WeakReference(java.lang.ref.WeakReference) Snackbar(com.google.android.material.snackbar.Snackbar) VisibleForTesting(androidx.annotation.VisibleForTesting) Sound(com.ichi2.libanki.Sound) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) Resources(android.content.res.Resources) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) Resources(android.content.res.Resources)

Example 7 with TTS

use of com.ichi2.anki.cardviewer.TTS in project AnkiChinaAndroid by ankichinateam.

the class ReadText method initializeTts.

public static String initializeTts(Context context, boolean vipSpeak, boolean showToast, ReadTextListener listener) {
    // Store weak reference to Activity to prevent memory leak
    mReviewer = new WeakReference<>(context);
    // Create new TTS object and setup its onInit Listener
    mTts = new TextToSpeech(context, status -> {
        if (status == TextToSpeech.SUCCESS) {
            // build list of available languages
            buildAvailableLanguages(TextToSpeech.LANG_AVAILABLE);
            if (availableTtsLocales.size() > 0) {
                // notify the reviewer that TTS has been initialized
                Timber.d("TTS initialized and available languages found");
                if (listener != null) {
                    listener.ttsInitialized();
                }
            // ((AbstractFlashcardViewer) mReviewer.get()).ttsInitialized();
            } else {
                if (showToast) {
                    Toast.makeText(mReviewer.get(), mReviewer.get().getString(R.string.no_tts_available_message), Toast.LENGTH_LONG).show();
                }
                Timber.w("TTS initialized but no available languages found");
            }
            mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {

                @Override
                public void onDone(String arg0) {
                    if (ReadText.sTextQueue.size() > 0) {
                        String[] text = ReadText.sTextQueue.remove(0);
                        ReadText.speak(text[0], text[1], TextToSpeech.QUEUE_FLUSH);
                    }
                    if (listener != null) {
                        listener.onDone();
                    }
                }

                @Override
                @Deprecated
                public void onError(String utteranceId) {
                    Timber.v("Andoid TTS failed. Check logcat for error. Indicates a problem with Android TTS engine.");
                    final Uri helpUrl = Uri.parse(mReviewer.get().getString(R.string.link_faq_tts));
                    final AnkiActivity ankiActivity = (AnkiActivity) mReviewer.get();
                    ankiActivity.mayOpenUrl(helpUrl);
                    if (showToast) {
                        UIUtils.showSnackbar(ankiActivity, R.string.no_tts_available_message, false, R.string.help, v -> openTtsHelpUrl(helpUrl), ankiActivity.findViewById(R.id.root_layout), new Snackbar.Callback());
                    }
                }

                @Override
                public void onStart(String arg0) {
                // no nothing
                }
            });
        } else {
            if (showToast) {
                Toast.makeText(mReviewer.get(), mReviewer.get().getString(R.string.no_tts_available_message), Toast.LENGTH_LONG).show();
            }
            Timber.w("TTS not successfully initialized");
        }
    });
    // Show toast that it's getting initialized, as it can take a while before the sound plays the first time
    if (showToast) {
        Toast.makeText(context, context.getString(R.string.initializing_tts), Toast.LENGTH_LONG).show();
    }
    return mTts.getDefaultEngine();
}
Also used : Context(android.content.Context) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) WindowManager(android.view.WindowManager) UtteranceProgressListener(android.speech.tts.UtteranceProgressListener) Compat(com.ichi2.compat.Compat) Timber(timber.log.Timber) ArrayList(java.util.ArrayList) TextToSpeech(android.speech.tts.TextToSpeech) Nullable(androidx.annotation.Nullable) Locale(java.util.Locale) Handler(android.os.Handler) Toast(android.widget.Toast) CompatHelper(com.ichi2.compat.CompatHelper) View(android.view.View) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) WeakReference(java.lang.ref.WeakReference) Snackbar(com.google.android.material.snackbar.Snackbar) VisibleForTesting(androidx.annotation.VisibleForTesting) Sound(com.ichi2.libanki.Sound) CustomStyleDialog(com.ichi2.ui.CustomStyleDialog) Resources(android.content.res.Resources) UtteranceProgressListener(android.speech.tts.UtteranceProgressListener) TextToSpeech(android.speech.tts.TextToSpeech) Uri(android.net.Uri) Snackbar(com.google.android.material.snackbar.Snackbar)

Example 8 with TTS

use of com.ichi2.anki.cardviewer.TTS in project AnkiChinaAndroid by ankichinateam.

the class Sound method playSoundInternal.

/**
 * Plays a sound without ensuring that the playAllListener will release the audio
 */
// audio API deprecation tracked on github as #5022
@SuppressWarnings({ "PMD.EmptyIfStmt", "PMD.CollapsibleIfStatements", "deprecation" })
private void playSoundInternal(String soundPath, OnCompletionListener playAllListener, VideoView videoView) {
    Timber.d("Playing %s has listener? %b", soundPath, playAllListener != null);
    Uri soundUri = Uri.parse(soundPath);
    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();
        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 && ThumbnailUtils.createVideoThumbnail(soundUri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND) != null;
        // 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, what, extra) -> {
                Timber.w("Media Error: (%d, %d). Calling OnCompletionListener", what, extra);
                return false;
            });
            // Setup the MediaPlayer
            mMediaPlayer.setDataSource(AnkiDroidApp.getInstance().getApplicationContext(), soundUri);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setOnPreparedListener(mp -> {
                Timber.d("Starting media player");
                mMediaPlayer.start();
            });
            if (playAllListener != null) {
                mMediaPlayer.setOnCompletionListener(playAllListener);
            }
            mMediaPlayer.prepareAsync();
            Timber.d("Requesting audio focus");
            mAudioManager.requestAudioFocus(afChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
        } catch (Exception e) {
            Timber.e(e, "playSounds - Error reproducing sound %s", soundPath);
            releaseSound();
        }
    }
}
Also used : AbstractFlashcardViewer(com.ichi2.anki.AbstractFlashcardViewer) Uri(android.net.Uri) MediaPlayer(android.media.MediaPlayer)

Example 9 with TTS

use of com.ichi2.anki.cardviewer.TTS in project Anki-Android by ankidroid.

the class AbstractFlashcardViewer method displayCardAnswer.

protected void displayCardAnswer() {
    // #7294 Required in case the animation end action does not fire:
    actualHideEaseButtons();
    Timber.d("displayCardAnswer()");
    mMissingImageHandler.onCardSideChange();
    mBackButtonPressedToReturn = false;
    // prevent answering (by e.g. gestures) before card is loaded
    if (mCurrentCard == null) {
        return;
    }
    // TODO needs testing: changing a card's model without flipping it back to the front
    // (such as editing a card, then editing the card template)
    mTypeAnswer.updateInfo(mCurrentCard, getResources());
    // but sometimes failed to do so (e.g. if an OnKeyListener is attached).
    if (mTypeAnswer.validForEditText()) {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(mAnswerField.getWindowToken(), 0);
    }
    sDisplayAnswer = true;
    mSoundPlayer.stopSounds();
    mAnswerField.setVisibility(View.GONE);
    // Clean up the user answer and the correct answer
    if (!mTypeAnswer.useInputTag()) {
        mTypeAnswer.setInput(mAnswerField.getText().toString());
    }
    mIsSelecting = false;
    CardHtml answerContent = mHtmlGenerator.generateHtml(mCurrentCard, false, Side.BACK);
    updateCard(answerContent);
    displayAnswerBottomBar();
    mAutomaticAnswer.onDisplayAnswer();
    // 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.scheduleAutomaticDisplayQuestion(mUseTimerDynamicMS);
    }
}
Also used : InputMethodManager(android.view.inputmethod.InputMethodManager) CardHtml(com.ichi2.anki.cardviewer.CardHtml)

Aggregations

Resources (android.content.res.Resources)5 Uri (android.net.Uri)4 ArrayList (java.util.ArrayList)4 MaterialDialog (com.afollestad.materialdialogs.MaterialDialog)3 Locale (java.util.Locale)3 Timber (timber.log.Timber)3 Context (android.content.Context)2 DialogInterface (android.content.DialogInterface)2 MediaPlayer (android.media.MediaPlayer)2 Handler (android.os.Handler)2 TextToSpeech (android.speech.tts.TextToSpeech)2 UtteranceProgressListener (android.speech.tts.UtteranceProgressListener)2 View (android.view.View)2 WindowManager (android.view.WindowManager)2 Toast (android.widget.Toast)2 NonNull (androidx.annotation.NonNull)2 Nullable (androidx.annotation.Nullable)2 VisibleForTesting (androidx.annotation.VisibleForTesting)2 Snackbar (com.google.android.material.snackbar.Snackbar)2 AbstractFlashcardViewer (com.ichi2.anki.AbstractFlashcardViewer)2