Search in sources :

Example 6 with Sound

use of com.ichi2.libanki.Sound 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);
            }
        }
    }
}
Also used : AbstractFlashcardViewer(com.ichi2.anki.AbstractFlashcardViewer) AudioAttributes(android.media.AudioAttributes) AudioFocusRequest(android.media.AudioFocusRequest) Uri(android.net.Uri) MediaPlayer(android.media.MediaPlayer)

Example 7 with Sound

use of com.ichi2.libanki.Sound in project Anki-Android by ankidroid.

the class CollectionTest method test_furigana.

@Test
@Ignore("Pending port of media search from Rust code")
public void test_furigana() {
    Collection col = getCol();
    ModelManager mm = col.getModels();
    Model m = mm.current();
    // filter should work
    m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:Front}}");
    mm.save(m);
    Note n = col.newNote();
    n.setItem("Front", "foo[abc]");
    col.addNote(n);
    Card c = n.cards().get(0);
    assertTrue(c.q().endsWith("abc"));
    // and should avoid sound
    n.setItem("Front", "foo[sound:abc.mp3]");
    n.flush();
    String question = c.q(true);
    assertThat("Question «" + question + "» does not contains «anki:play».", question, containsString("anki:play"));
    // it shouldn't throw an error while people are editing
    m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:}}");
    mm.save(m);
    c.q(true);
}
Also used : Matchers.containsString(org.hamcrest.Matchers.containsString) Ignore(org.junit.Ignore) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 8 with Sound

use of com.ichi2.libanki.Sound in project Anki-Android by Ramblurr.

the class NoteService method updateMultimediaNoteFromJsonNote.

public static void updateMultimediaNoteFromJsonNote(final Note editorNoteSrc, final IMultimediaEditableNote noteDst) {
    if (noteDst instanceof MultimediaEditableNote) {
        MultimediaEditableNote mmNote = (MultimediaEditableNote) noteDst;
        String[] values = editorNoteSrc.getFields();
        for (int i = 0; i < values.length; i++) {
            String value = values[i];
            IField field = null;
            if (value.startsWith("<img")) {
                field = new ImageField();
            } else if (value.startsWith("[sound:")) {
                field = new AudioField();
            } else {
                field = new TextField();
            }
            field.setFormattedString(value);
            mmNote.setField(i, field);
        }
        mmNote.setModelId(editorNoteSrc.getMid());
    // TODO: set current id of the note as well
    }
}
Also used : AudioField(com.ichi2.anki.multimediacard.fields.AudioField) ImageField(com.ichi2.anki.multimediacard.fields.ImageField) MultimediaEditableNote(com.ichi2.anki.multimediacard.impl.MultimediaEditableNote) IMultimediaEditableNote(com.ichi2.anki.multimediacard.IMultimediaEditableNote) TextField(com.ichi2.anki.multimediacard.fields.TextField) IField(com.ichi2.anki.multimediacard.fields.IField)

Example 9 with Sound

use of com.ichi2.libanki.Sound 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 10 with Sound

use of com.ichi2.libanki.Sound 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)

Aggregations

Test (org.junit.Test)5 Uri (android.net.Uri)3 Note (com.ichi2.libanki.Note)3 MediaPlayer (android.media.MediaPlayer)2 AbstractFlashcardViewer (com.ichi2.anki.AbstractFlashcardViewer)2 RobolectricTest (com.ichi2.anki.RobolectricTest)2 IField (com.ichi2.anki.multimediacard.fields.IField)2 ImageField (com.ichi2.anki.multimediacard.fields.ImageField)2 TextField (com.ichi2.anki.multimediacard.fields.TextField)2 Collection (com.ichi2.libanki.Collection)2 Sound (com.ichi2.libanki.Sound)2 Anki2Importer (com.ichi2.libanki.importer.Anki2Importer)2 AnkiPackageImporter (com.ichi2.libanki.importer.AnkiPackageImporter)2 Importer (com.ichi2.libanki.importer.Importer)2 NoteImporter (com.ichi2.libanki.importer.NoteImporter)2 TextImporter (com.ichi2.libanki.importer.TextImporter)2 File (java.io.File)2 FileOutputStream (java.io.FileOutputStream)2 ArrayList (java.util.ArrayList)2 Matchers.containsString (org.hamcrest.Matchers.containsString)2