use of com.ichi2.libanki.Media in project Anki-Android by ankidroid.
the class Media method maybeUpgrade.
public void maybeUpgrade() {
String oldpath = dir() + ".db";
File oldDbFile = new File(oldpath);
if (oldDbFile.exists()) {
mDb.execute(String.format(Locale.US, "attach \"%s\" as old", oldpath));
try {
String sql = "insert into media\n" + " select m.fname, csum, mod, ifnull((select 1 from log l2 where l2.fname=m.fname), 0) as dirty\n" + " from old.media m\n" + " left outer join old.log l using (fname)\n" + " union\n" + " select fname, null, 0, 1 from old.log where type=" + Consts.CARD_TYPE_LRN + ";";
mDb.execute(sql);
mDb.execute("delete from meta");
mDb.execute("insert into meta select dirMod, usn from old.meta");
mDb.commit();
} catch (Exception e) {
// if we couldn't import the old db for some reason, just start anew
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
mCol.log("failed to import old media db:" + sw.toString());
}
mDb.execute("detach old");
File newDbFile = new File(oldpath + ".old");
if (newDbFile.exists()) {
newDbFile.delete();
}
oldDbFile.renameTo(newDbFile);
}
}
use of com.ichi2.libanki.Media 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.libanki.Media in project Anki-Android by ankidroid.
the class RemoteMediaServer method downloadFiles.
/**
* args: files
* <br>
* This method returns a ZipFile with the OPEN_DELETE flag, ensuring that the file on disk will
* be automatically deleted when the stream is closed.
*/
public ZipFile downloadFiles(List<String> top) throws UnknownHttpResponseException {
Response resp = null;
try {
resp = super.req("downloadFiles", HttpSyncer.getInputStream(Utils.jsonToString(new JSONObject().put("files", new JSONArray(top)))));
String zipPath = mCol.getPath().replaceFirst("collection\\.anki2$", "tmpSyncFromServer.zip");
// retrieve contents and save to file on disk:
super.writeToFile(resp.body().byteStream(), zipPath);
return new ZipFile(new File(zipPath), ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
} catch (IOException | NullPointerException e) {
Timber.e(e, "Failed to download requested media files");
throw new RuntimeException(e);
} finally {
if (resp != null && resp.body() != null) {
resp.body().close();
}
}
}
use of com.ichi2.libanki.Media 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);
}
use of com.ichi2.libanki.Media in project Anki-Android by ankidroid.
the class AnkiPackageExporterTest method checkMediaExportStringIs.
private void checkMediaExportStringIs(File[] files, String s) throws IOException {
for (File f : files) {
if (!"media".equals(f.getName())) {
continue;
}
List<String> lines = Arrays.asList(getFileContents(f).split("\n"));
assertThat(lines, contains(s));
return;
}
Assert.fail("media file not found");
}
Aggregations